я попытался найти способ устранить неоднозначность этого кода (во время компиляции) (так как два дня 🙂 -> get_value неоднозначно.
#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;
}
Это рабочее решение во время выполнения.
#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;
}
Есть ли решение?
Примечание: возможный способ, который я нашел, это через std :: is_base_of<>, но это очень ограничено (глубина создания шаблона)
Это неоднозначный поиск имен, который в случае множественного наследования скрывает имена в поиске. Он даже не проверяет, какую перегрузку использовать.
Вы можете исправить это, добавив следующее в struct A
определение:
using BASE<X,1>::get_value;
using BASE<Y,0>::get_value;
Эти два утверждения добавляют название get_value
от обоих базовых классов до A, и, таким образом, компилятор может затем продолжить свою унылую жизнь и проверить их как перегрузки.
Основываясь на ответе Аташа: Предполагая, что вы не хотите перепечатывать список базовых классов в списке баз и в декларациях использования, вы можете использовать косвенное обращение, подобное этому:
#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;
}