c++ - 为什么 SFINAE 只适用于这两个看似相同的功能之一?
问题描述
以下代码无法编译(使用 clang 7.0,--std=c++17):
struct Foo {
void foo() {}
};
struct Bar {
void bar() {}
};
struct Both {
void foo() {}
void bar() {}
};
template <typename T, typename>
void DoStuff(T input) {
input.foo();
}
template <typename T, typename...>
void DoStuff(T input) {
input.bar();
}
int main(int argc, char** argv) {
DoStuff(Foo());
return 0;
}
错误是:
<source>:19:11: error: no member named 'bar' in 'Foo'
input.bar();
~~~~~ ^
<source>:23:5: note: in instantiation of function template specialization 'DoStuff<Foo>' requested here
DoStuff(Foo());
但是,如果您更改Foo()
为Bar()
(or Both()
),它编译就好了。在Bar()
本案中,这表明SFINAE正在生效;在这种Both()
情况下,它表明typename...
重载的优先级较低,因此在两者都适用时选择另一个。
但是我不明白的是为什么SFINAE适用于Bar()
该案而不适用于Foo()
该案?
解决方案
这里没有 SFINAE。所有的电话DoStuff
都会打电话
template <typename T, typename...>
void DoStuff(T input) {
input.bar();
}
这样做的原因是
template <typename T, typename>
void DoStuff(T input) {
input.foo();
}
需要两个模板参数,而
template <typename T, typename...>
void DoStuff(T input) {
input.bar();
}
适用于 1 个或多个模板参数(可变参数包允许为空)。所以当你打电话
DoStuff(Foo());
// or
DoStuff(Bar());
//or
DoStuff(Both());
你只能推导出一个模板参数,唯一可行的候选者是
template <typename T, typename...>
void DoStuff(T input) {
input.bar();
}
如果你用过
DoStuff<Foo, any_other_type>(Foo());
那么你会得到一个模棱两可的错误,因为它匹配两个模板。
推荐阅读
- angular - 如何从材料角度的日期范围日期选择器中获取值(从日期到日期)
- bash - 如何加快为列表中的每个条目生成 jvm 并关闭的 for 循环?
- logstash - 删除 Logstash 配置文件中不需要的字段
- xml - 在 Angular 2+ 中渲染 XML
- visual-studio - LNK1112:模块机器类型“x64”与目标机器类型“x86”冲突-opencv 构建
- javascript - JS 中的这些参数是什么?
- r - 如何在多条件下在 R 中绘制 3D
- java - 使用 Java8 Stream 从列表或集合中查找最高值
- swift - Swift AppleScript 内存泄漏
- php - 仅当从程序内启动 xampp 服务器时才返回问号而不是阿拉伯字符