c++ - Eliminate redundancy with CRTP and multiple inheritance -
this question c++03, not c++11.
i have case using crtp multiple inheritance, , curious know if there way remove redundancy created when specifying type of b
below.
#include "boost/typeof/typeof.hpp" #include "boost/units/detail/utility.hpp" #include <iostream> #include <string> struct one{}; struct two{}; template<typename t> struct type { static std::string name(void) { return boost::units::detail::demangle(typeid(t).name()); } }; template<typename t1, typename t2> struct { typedef a<t1, t2> self; a() { std::cout << type<self>::name() << std::endl; } }; template<typename t1, typename t2, typename t3> struct b : public a<one, b<t1, t2, t3> >, // b<t1, t2, t3> here redundant public a<two, b<t1, t2, t3> > { typedef b<t1, t2, t3> self; b() { std::cout << type<self>::name() << std::endl; } }; int main(int argc, char* argv[]) { b<int, int, int> t; return 0; }
see on coliru
the problem worsens when number of template parameters b
increases, when template arguments complex, , when b
inherits a
more times. i'd minimize repetition of b
's template parameters. specifically, looking way access typedef b<t1, t2, t3> self
in inheritance list b
, or equivalent compile-time version of this
.
i cannot:
- make typedef
b
aboveb
using forward declaration, because don't have access template parameters - make typedef inside of inheritance definition because syntax doesn't allow that
- access typedef inside class, because doesn't exist yet
something below (none of not valid code, display effect looking for):
template<typename t1, typename t2, typename t3> struct b : public a<one, self>, // cannot access typedef yet public a<two, self> { typedef b<t1, t2, t3> self; }; template<typename t1, typename t2, typename t3> struct b : typedef b<t1, t2, t3> self, // invalid syntax public a<one, self>, public a<two, self> { }; template<typename t1, typename t2, typename t3> struct b : public a<one, b>, // wish work public a<two, b> { }; template<typename t1, typename t2, typename t3> struct b : public a<one, boost_typeof(*this)>, // lol public a<two, boost_typeof(*this)> { };
is there way access compile-time version of this
?
the problem with:
template<typename t1, typename t2, typename t3> struct b : public a<one, b>, // wish work public a<two, b> { };
is template <typename t1, typename t2> struct a
asks instantiated t2
type, whereas wish instantiate t2
template, namely template<typename, typename,typename> struct b
.
if definition of a
lies in own control, perhaps - though perhaps not - solution make definition of a
consistent wish:
#include "boost/typeof/typeof.hpp" #include "boost/units/detail/utility.hpp" #include <iostream> #include <string> struct one{}; struct two{}; template<typename t> struct type { static std::string name(void) { return boost::units::detail::demangle(typeid(t).name()); } }; template<typename t1, template<typename, typename, typename> class t2 > struct { a() { std::cout << type<a>::name() << std::endl; } }; template<typename t1, typename t2, typename t3> struct b : public a<one, b >, public a<two, b > { b() { std::cout << type<b>::name() << std::endl; } }; int main(int argc, char* argv[]) { b<int, int, int> t; return 0; }
this program prints:
a<one, b> a<two, b> b<int, int, int>
the price of solution restricting classes a
can furnish crtp base ones instantiate template, b
, of 3 typename
parameters.
perhaps lucky enough restriction not thwart other wishes have. if need a
furnish crtp base classes instantiate template not have 3 typename
parameters, bites.
provided of classes need a
furnish crtp base instantiations of templates have typename
parameters, , have @ n
of them, can still have c++03 solution in same spirit:
you define a
per schema:
template<typename t1, template<typename /*1*/,.... typename /*n*/> class t2 > struct { ... };
and each template y
a
crtp base, provide n
parameters, employing "padding" parameters default void
, necessary. example, if n
== 3:
#include "boost/typeof/typeof.hpp" #include "boost/units/detail/utility.hpp" #include <iostream> #include <string> struct one{}; struct two{}; template<typename t> struct type { static std::string name(void) { return boost::units::detail::demangle(typeid(t).name()); } }; template<typename t1, template<typename, typename, typename> class t2 > struct { a() { std::cout << type<a>::name() << std::endl; } }; template<typename t1, typename t2 = void, typename t3 = void> struct b : public a<one, b >, public a<two, b > { b() { std::cout << type<b>::name() << std::endl; } }; template<typename t1, typename t2, typename t3 = void> struct c : public a<one, c >, public a<two, c > { c() { std::cout << type<c>::name() << std::endl; } }; template<typename t1, typename t2, typename t3> struct d : public a<one, d >, public a<two, d > { d() { std::cout << type<d>::name() << std::endl; } }; int main(int argc, char* argv[]) { b<int> b; c<int,int> c; d<int,int,int> d; return 0; }
this program prints:
a<one, b> a<two, b> b<int, void, void> a<one, c> a<two, c> c<int, int, void> a<one, d> a<two, d> d<int, int, int>
true, more general solution sticks different kind of "redundancy", in form of superfluous defaulted template parameters. may find less irksome kind.
(gcc 5.1/clang 3.6, c++03)
Comments
Post a Comment