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
inheritsuvector<t>
, first static function choosed, , decltype returnforwarder<uvector<t>>
. then, 'calling'::value
on callaccepted...
. - else, if
c
not inheritsuvector<t>
, second function choosed, , decltype returnstd::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
Post a Comment