【发布时间】:2019-09-19 02:48:44
【问题描述】:
考虑以下 MCVE
struct A {};
template<class T>
void test(T, T) {
}
template<class T>
class Wrapper {
using type = typename T::type;
};
template<class T>
void test(Wrapper<T>, Wrapper<T>) {
}
int main() {
A a, b;
test(a, b); // works
test<A>(a, b); // doesn't work
return 0;
}
这里test(a, b); 有效,test<A>(a, b); 失败:
<source>:11:30: error: no type named 'type' in 'A'
using type = typename T::type;
~~~~~~~~~~~~^~~~
<source>:23:13: note: in instantiation of template class 'Wrap<A>' requested here
test<A>(a, b); // doesn't work
^
<source>:23:5: note: while substituting deduced template arguments into function template 'test' [with T = A]
test<A>(a, b); // doesn't work
问题:为什么会这样?在替换期间,SFINAE 不应该工作吗?然而在这里它似乎只在演绎期间起作用。
【问题讨论】:
-
在
test(a, b);中,T不能推导出test的第二个重载,所以这个重载在Wrapper<A>的实例化之前被丢弃了,所以候选列表只包含首先是test,这就是它起作用的原因。在第二种情况下,第二个重载是有效的候选者,因为显式提供了T,因此暗示Wrapper<A>的实例化失败。 -
只是好奇:你在这里的意图是什么?根据
::type成员类型的存在选择不同的重载? -
@LF 的目的是将模板限制为
Wrapper<T>类型,看起来它有时像 SFINAE 一样工作,但显然它没有。
标签: c++ c++11 templates language-lawyer sfinae