SFINAE没有避免歧义调用
Ambiguous call not avoided by SFINAE
编译代码:
#include <iostream>
template <int N>
struct TestClass {
template <int N2, typename std::enable_if<N2 == N, int>::type = 0>
void doAction() { std::cout << "TestClass::doAction<" << N << ">();n"; }
};
struct HostClass : public TestClass<1>, public TestClass<2> {
};
int main(int argc, const char * argv[]) {
HostClass hostClass;
hostClass.doAction<1>();
hostClass.doAction<2>();
return 0;
}
会导致歧义调用错误,因为doAction
同时在TestClass<1>
和TestClass<2>
父类中。
main.cpp:33:15:在不同类型的多个基类中发现成员'doAction'
但std::enable_if
不会使这种模糊性失效?
我认为这种模棱两可的真正原因和这个问题是一样的:
为什么具有相同名称但不同签名的多继承函数不被视为重载函数?
歧义可以用using
关键字解决,如答案所示:
#include <iostream>
template <int N>
struct TestClass {
template <int N2, typename std::enable_if<N2 == N, int>::type = 0>
void doAction() { std::cout << "TestClass::doAction<" << N << ">();n"; }
};
struct HostClass : public TestClass<1>, public TestClass<2> {
using TestClass<1>::doAction;
using TestClass<2>::doAction;
};
int main(int argc, const char * argv[]) {
HostClass hostClass;
hostClass.doAction<1>(); // OK, compile
hostClass.doAction<2>(); // OK, compile
//hostClass.doAction<3>(); // OK, doesn't compile : "candidate template ignored: disabled by 'enable_if' [with N2 = 3]"
return 0;
}
我不知道这是不是@skypjack answer的意思,但我还是让它替代了它的方法。
它会(让我说)将放在替换后的两个函数之一。
无论如何,首先,编译器必须决定你打算使用哪个函数,当你调用它作为doAction<1>
, 然后它可以继续进行替换,最终扔掉选择的函数,因为sfinae。在调用时,它们都是有效的候选者,并且调用实际上是二义性的。
请注意,正如@Peregring-lk在评论中建议的那样,TestClass<1>::doAction
和TestClass<2>::doAction
是放置在不同命名空间中的两个不同的函数,它们不是同一函数的重载。
这实际上是误解的一个常见来源。
你可以很容易地解决这个问题,如下所示:
#include <iostream>
template <int N>
struct TestClass {
void doAction() { std::cout << "TestClass::doAction<" << N << ">();n"; }
};
struct HostClass : public TestClass<1>, public TestClass<2> {
template<int N>
void doAction() { return TestClass<N>::doAction(); }
};
int main(int argc, const char * argv[]) {
HostClass hostClass;
hostClass.doAction<1>();
hostClass.doAction<2>();
return 0;
}
相关文章:
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- std::bind 是否实现了 std::ref 和 std::cref 来消除函数调用的歧义?
- C++ 类的构造函数和函数调用运算符 () 重载之间的歧义
- 如何让编译器知道要调用函数的哪个重载以避免歧义?
- 函数调用歧义(用户定义的转换和 Derived2Base 指针转换)
- 函数调用带有指针、引用和常量引用参数的歧义
- 调用模板函数时出现歧义
- 解决C++构造函数和调用歧义
- 在隐式转换后的智能指针上删除函数调用中的歧义
- 为什么在这个函数调用中没有歧义
- 嵌套类中对运算符[]的调用存在歧义
- 推导函数调用时出现歧义问题
- C++方法调用和类型范围解析的歧义
- 调用函数的歧义.隐式转换
- Visual Studio c++对重载函数的歧义调用
- 多个操作符重载会导致歧义调用
- SFINAE没有避免歧义调用
- 当添加模板参数时,重载解析会产生歧义调用
- GCC声明友元函数是重载的,有歧义调用,clang编译
- 歧义调用(从char*到lambda与std::string的转换)