c++ - 就 SFINAE 而言,访问不存在的成员是否不被视为“错误”?
问题描述
我已经为漂亮的打印对实现了重载:
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]')
我不太明白问题是什么。我试图打印的 char 数组显然没有first
orsecond
成员,所以用我的重载实例化它会导致错误。
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;
}
推荐阅读
- c# - 如何在 .Net C# Windows 窗体中将文件上传到 Firebase 存储?
- python - 如何增强脚本以从多个 CSV 文件中查找
- c# - 为什么这个属性没有在我的 mvc 项目中被序列化?
- pandas - pd.datetime 没有正确索引
- c++ - 从成员函数返回 boost iterator_range
- git - 丢弃工作目录中的更改使其无法跟踪。我如何重新跟踪它?
- python - 将字符串转换为列表时出现 EOFError
- php - SSL 已启用,但网站拒绝安全加载
- java - 如何在不关联数据的情况下通过协作通道适配器发送异步请求/响应
- python - 用于多个值的 Python STDIN