就 SFINAE 而言,访问不存在的成员是否不被视为 "error"?
Is accessing a non-existent member NOT considered an "error" as far as SFINAE is concerned?
我已经为漂亮的打印对实现了重载:
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 仅适用于函数签名:即参数类型、return 类型和限定符,例如:const
、非const
。它不适用于函数的实现。
在您的情况下,函数签名与调用匹配。因此,该函数已实例化,预计可以无错编译。
SFINAE 在重载解析期间工作:
This rule applies during overload resolution of function templates: When substituting the explicitly specified or deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error.
也就是说只有函数模板的签名才会对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;
}
我已经为漂亮的打印对实现了重载:
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 仅适用于函数签名:即参数类型、return 类型和限定符,例如:const
、非const
。它不适用于函数的实现。
在您的情况下,函数签名与调用匹配。因此,该函数已实例化,预计可以无错编译。
SFINAE 在重载解析期间工作:
This rule applies during overload resolution of function templates: When substituting the explicitly specified or deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error.
也就是说只有函数模板的签名才会对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;
}