und*_*ica 2 c++ templates sfinae
我为漂亮的打印对实现了一个重载:
template<typename P>
ostream &operator<<(ostream &os, const P &p) {
using std::operator<<;
os << '(' << p.first << ", " << p.second << ')';
return os;
}
Run Code Online (Sandbox Code Playgroud)
但是,在它存在的情况下,编译器无法确定是应该应用标准重载还是应用上面定义的重载,即使选择应该是明显的:
int main() {
cout << "SFINAE sure is hard to grasp!\n";
}
error: use of overloaded operator '<<' is
ambiguous (with operand types 'std::ostream' (aka 'basic_ostream<char>') and
'const char [30]')
Run Code Online (Sandbox Code Playgroud)
我不太明白问题是什么.我正在尝试打印的char数组没有first或没有second成员,所以用我的重载实例化它会导致错误.
SFINAE不应该尝试执行替换,发现缺少成员,并丢弃结果吗?如果没有,为什么?
SFINAE在重载解析期间工作:
此规则适用于函数模板的重载解析期间:当替换显式指定或推断的类型的模板参数失败时,将从重载集中丢弃特化而不是导致编译错误.
这意味着只有功能模板的签名才会对SFINAE生效,不会检查实现.
您可以将重载更改为
template <typename T, typename = void>
struct pairable : std::false_type {};
// check whether type T has first and second members
template <typename T>
struct pairable<T, std::void_t<decltype(std::declval<T>().first),
decltype(std::declval<T>().second)>>
: std::true_type {};
// the template parameter is the part of the signature of function template
template<typename P, std::enable_if_t<pairable<P>::value>* = nullptr>
ostream &operator<<(ostream &os, const P &p) {
using std::operator<<;
os << '(' << p.first << ", " << p.second << ')';
return os;
}
Run Code Online (Sandbox Code Playgroud)
SFINAE仅适用于函数签名:即参数类型,返回类型和限定符,例如:const,non const.它不适用于函数的实现.
在您的情况下,函数签名与调用匹配.因此,该函数被实例化,并且预期编译时没有错误.