шаблоны — C ++: устранение неоднозначности этого кода во время компиляции?

я попытался найти способ устранить неоднозначность этого кода (во время компиляции) (так как два дня 🙂 -> 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<>, но это очень ограничено (глубина создания шаблона)

6

Решение

Это неоднозначный поиск имен, который в случае множественного наследования скрывает имена в поиске. Он даже не проверяет, какую перегрузку использовать.

Вы можете исправить это, добавив следующее в struct Aопределение:

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

Эти два утверждения добавляют название get_value от обоих базовых классов до A, и, таким образом, компилятор может затем продолжить свою унылую жизнь и проверить их как перегрузки.

7

Другие решения

Основываясь на ответе Аташа: Предполагая, что вы не хотите перепечатывать список базовых классов в списке баз и в декларациях использования, вы можете использовать косвенное обращение, подобное этому:

#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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector