C ++: eliminate this code at compile time?

I tried to find a way to eliminate this code (at compile time) (since two days :-) β†’ get_value is depressing.

#include <iostream> template <typename T> struct type2type {}; template<class T, int val> struct BASE { static constexpr int get_value ( type2type< T > ) { return val; } }; class X {}; class Y {}; struct A : public BASE< X, 1 >, public BASE< Y, 0 > {}; int main ( int argc, char **argv ) { A a {}; std::cout << a.get_value ( type2type< X >{} ) << std::endl; } 

This is the working time.

 #include <iostream> template <typename T> struct type2type {}; template<class T> struct VIRTUAL { int get_value () const { return get_value_from_BASE ( type2type< T > {} ); } private: virtual int get_value_from_BASE ( type2type< T > ) const = 0; }; template<class T, int val> class BASE : public VIRTUAL< T > { virtual int get_value_from_BASE ( type2type< T > ) const override { return val; } }; class X {}; class Y {}; struct A : public BASE< X, 1 >, public BASE< Y, 0 > {}; int main ( int argc, char **argv ) { A a {}; std::cout << a.::VIRTUAL< X >::get_value () << std::endl; } 

Is there a solution?

Note. The possible way I found is above std :: is_base_of <>, but it is very small (depth of the template instance)

+6
source share
2 answers

This is an ambiguous name search, which, in the case of multiple inheritance, hides the names in the search. It does not even check which overload to use.

You can fix this by adding the following to the definition of struct A :

 using BASE<X,1>::get_value; using BASE<Y,0>::get_value; 

These two statements add the name get_value from both base classes to A, and so the compiler can go on to their boring life and test them as overloads.

+7
source

Based on Atash’s answer: Assuming you don’t want to retype the list of base classes in the list of bases and in usage declarations, you can use indirect actions as follows:

 #include <iostream> template <typename T> struct type2type {}; template<class T, int val> struct BASE { static constexpr int get_value ( type2type< T > const& ) { return val; } }; class X {}; class Y {}; template <typename...> struct AUX; template <typename Base, typename... Bases> struct AUX<Base, Bases...>: Base, AUX<Bases...> { using Base::get_value; using AUX<Bases...>::get_value; }; template <typename Base> struct AUX<Base>: Base { using Base::get_value; }; struct A : public AUX<BASE< X, 1 >, BASE< Y, 0 > > { }; int main () { A a {}; std::cout << a.get_value ( type2type< X >() ) << std::endl; } 
+2
source

Source: https://habr.com/ru/post/951516/


All Articles