我实现了漂亮的印刷对过载:
template<typename P>
ostream &operator<<(ostream &os, const P &p) {
using std::operator<<;
os << '(' << p.first << ", " << p.second << ')';
return os;
}
然而,在其存在的编译器有麻烦告诉它是否适用标准过载或我上面定义的,即使是在选择的时候应该是很明显的例子之一:
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]')
我不太明白是什么问题。该字符数组我想清晰地打印有没有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;
}
SFINAE只适用于功能签名:即参数类型,返回类型,和限定符,如:const
,非const
。它并不适用于功能的实现。
在你的情况,函数签名的呼叫匹配。因此,该函数被实例化,并有望没有错误编译。