c++ - Substitute fully instantiated classes with partially instantiated ancestor classes -


i want accepted_dense_vector<??>::value return 'true' when give template parameters in form:

c<t> when c uvector, dynamic_array , t std::is_arithmetic.

std::array<t,s> when t std::is_arithmetic.

container_reference<c> when accepted_dense_vector<c>::value 'true'.

all works fine, in derived, instantiated classes a, c, d, want remove workaround parent definition.

how can this?

#include <iostream> #include <array> using namespace std;  // definition of used types. template<typename t> struct dynamic_array {}; template<typename t> struct uvector {}; struct : public uvector<double> { typedef uvector<double> parent; }; struct c : public { typedef parent; }; struct d : public std::array<double,5> { typedef std::array<double,5> parent; }; template<typename t> struct b : public uvector<t> { typedef uvector<t> parent; }; template<typename t> struct container_reference {};  // catches 'false', a, c, d  ======== here !!! ======== template<typename c> struct accepted_dense_vector {     template<typename c1 = c>     static typename std::enable_if<accepted_dense_vector<typename c1::parent>::value, std::true_type>::type helper(const c&);     static std::false_type helper(...);      constexpr static bool value = decltype(helper(std::declval<c>()))::value; }; // catches c<t> template<template<typename> class c, typename t> struct accepted_dense_vector<c<t>> {     constexpr static bool value = std::is_arithmetic<t>::value &&         (std::is_base_of<uvector<t>, c<t>>::value || std::is_base_of<dynamic_array<t>, c<t>>::value); }; // catches std::array<t,s> template<typename t, size_t s> struct accepted_dense_vector<std::array<t,s>>     { constexpr static bool value = std::is_arithmetic<t>::value; };  // catches container_reference<c> template<typename c> struct accepted_dense_vector<container_reference<c>>     { constexpr static bool value = accepted_dense_vector<c>::value; };  int main() { // tests!     cout << accepted_dense_vector<std::array<double, 5>>::value << endl;     cout << accepted_dense_vector<uvector<double>>::value << endl;     cout << accepted_dense_vector<a>::value << endl;     cout << accepted_dense_vector<d>::value << endl;     cout << accepted_dense_vector<b<int>>::value << endl;     cout << accepted_dense_vector<container_reference<uvector<double>>>::value << endl;     cout << accepted_dense_vector<int>::value << endl;      return 0; } 

you can go further solution. first, not need std::enable_if. code more readable. then, instead of using std::true_type, use custom struct call accepted_dense_vector:

template<typename t> struct forwarder {     constexpr static bool value = accepted_dense_vector<t>::value; };  template<typename t> static forwarder<uvector<t>> inherit_uvector(uvector<t>*);  static std::false_type inherit_uvector(...); 

then, know whether type satisfy accepted... inheritance of uvector<t>, use following line:

constexpr static bool is_uvector = decltype(inherit_uvector(new c()))::value; // c template parameter of accepted_dense_vector 

how works ?

  • if c inherits uvector<t>, first static function choosed, , decltype return forwarder<uvector<t>>. then, 'calling' ::value on call accepted....
  • else, if c not inherits uvector<t>, second function choosed, , decltype return std::false_type.

the same trick can used other inheritances. also, b<t> catched second specialization of accepted.... thus, ::parent typedef not needed anymore.

here full code (live here):

#include <iostream> #include <array> #include <string> using namespace std;  // definition of used types. template<typename t> struct uvector {}; template<typename t> struct dynamic_array {}; template<typename t> struct container_reference {};  struct : public uvector<double> {}; template<typename t> struct b : public uvector<t> {}; struct c : public {}; struct d : public std::array<double,5> {}; struct e : public uvector<string> {}; struct f : public std::array<string,16> {};  // catches 'false', a, c, d  ======== here !!! ======== template<typename c> struct accepted_dense_vector {    template<typename t>    struct forwarder    {       constexpr static bool value = accepted_dense_vector<t>::value;    };     // uvector    template<typename t>    static forwarder<uvector<t>> inherit_uvector(uvector<t>*);    static std::false_type inherit_uvector(...);     // std::array    template<typename t, size_t s>    static forwarder<std::array<t,s>> inherit_stdarray(std::array<t,s>*);    static std::false_type inherit_stdarray(...);     // same dynamic_array<t>      constexpr static bool is_uvector = decltype(inherit_uvector(new c()))::value;     constexpr static bool is_stdarray = decltype(inherit_stdarray(new c()))::value;     constexpr static bool value = is_uvector || is_stdarray; };   // catches c<t> // /!\ catches template<typename> class (for example, b) // => b::parent not needed, because of use of std::is_base_of template<template<typename> class c, typename t> struct accepted_dense_vector<c<t>> {     constexpr static bool value = std::is_arithmetic<t>::value &&         (std::is_base_of<uvector<t>, c<t>>::value || std::is_base_of<dynamic_array<t>, c<t>>::value); };  // catches std::array<t,s> template<typename t, size_t s> struct accepted_dense_vector<std::array<t,s>> {    constexpr static bool value = std::is_arithmetic<t>::value; };  // catches container_reference<c> template<typename c> struct accepted_dense_vector<container_reference<c>> {    constexpr static bool value = accepted_dense_vector<c>::value; };  int main() { // tests!     cout << "array = " << accepted_dense_vector<std::array<double, 5>>::value << endl;     cout << "uvector = " << accepted_dense_vector<uvector<double>>::value << endl;     cout << "ref = " << accepted_dense_vector<container_reference<uvector<double>>>::value << endl;     cout << "a = " << accepted_dense_vector<a>::value << endl;     cout << "b = " << accepted_dense_vector<b<int>>::value << endl;     cout << "c = " << accepted_dense_vector<c>::value << endl;     cout << "d = " << accepted_dense_vector<d>::value << endl;     cout << "e = " << accepted_dense_vector<e>::value << endl;     cout << "f = " << accepted_dense_vector<f>::value << endl;     cout << "int = " << accepted_dense_vector<int>::value << endl;      return 0; } 

Comments

Popular posts from this blog

Delphi XE2 Indy10 udp client-server interchange using SendBuffer-ReceiveBuffer -

Qt ActiveX WMI QAxBase::dynamicCallHelper: ItemIndex(int): No such property in -

Enable autocomplete or intellisense in Atom editor for PHP -