代码如下:
#include <utility>
#include <type_traits>
template <class T>
class ClassWithDisabledFoo
{
public:
template <class U = T, std::enable_if_t<std::is_integral<U>::value, int> = 0>
void foo(){}
};
class ClassWithFoo
{
public:
void foo(){}
};
class Derived: public ClassWithFoo, public ClassWithDisabledFoo<double>
{
};
void test()
{
Derived d;
d.foo();
}
在调用d.foo()
时,clang和gcc都表示对foo
的调用是不明确的,尽管ClassWithDisabledFoo::foo
被 enable_if
禁用。如果我将 foo
定义从 ClassWithFoo
移动到 Derived
,代码就会编译。
为什么这不起作用?我怎样才能使它起作用?
最佳答案
您的示例中没有发生重载解析,因此 SFINAE 并不重要。
这里的关键是名称查找发生在重载解析之前。名称查找找到重载集,然后对找到的集执行重载解析。
名称必须映射到单个对象类型内的单个集合。在您的情况下,相同的名称映射到两个不同子对象的成员,因此名称查找不明确。立即的解决方案是添加 using 声明:
class Derived: public ClassWithFoo, public ClassWithDisabledFoo<double>
{
using ClassWithFoo::foo;
using ClassWithDisabledFoo::foo;
};
这会将名称引入到 Derived
中,现在可以明确地找到声明引用由我们引入的成员组成的重载集。
关于c++ - 为什么 SFINAE 不能跨多重继承工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59178136/