我试图找到一种消除这种代码歧义的方法(在编译时)(因为两天:-) - > get_value是ambugiuous。
#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&lt;&gt;,但这是非常有限的(模板实例化深度)
答案 0 :(得分:7)
这是一个模糊的名称查找,在多重继承的情况下,会在查找中隐藏名称。它甚至无法检查使用哪个过载。
您可以通过在struct A
的定义中添加以下内容来解决此问题:
using BASE<X,1>::get_value;
using BASE<Y,0>::get_value;
这两个语句将两个基类中的名称get_value
添加到A中,因此编译器可以继续使用其沉闷的生命并将其作为重载进行检查。
答案 1 :(得分:2)
以Atash的答案为基础:假设您不想在基数列表和使用声明中重新键入基类列表,您可以使用这样的间接:
#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;
}