在this帖子中,建议使用以下方法为定义operator<<
成员函数的所有类定义dump()
函数:
template <typename T, typename charT>
auto operator<< (std::basic_ostream<charT> & str, const T & t) -> decltype(t.dump(str))
{
return t.dump(str);
}
为什么这个功能模板没有捕获所有类型,包括那些不定义dump
成员函数的类型?我的意思是,函数签名的返回类型部分是在选择重载时考虑的吗?
答案 0 :(得分:7)
返回类型本身并不重要。当声明对实例化无效时,所提出的技术依赖于SFINAE(替换失败不是错误)来删除重载。也就是说,当编译器尝试使用类型为MAX()
并且没有可访问operator<<()
成员的上述T
实例化时,dump(str)
将无效。而不是失败它决定了这个过载不会起作用并将其从候选过载集中删除。
收集候选人后,重载决议会选择最佳选项。如果最佳选项是唯一的,则选择它进行调用。如果没有拟合选项或有多个最佳匹配,那将是一个错误。
答案 1 :(得分:2)
此行为不是归因于重载决策规则,而是归因于模板参数推断规则。特别是归因于SFINAE(也就是替换失败不是错误)。
在模板参数推导中,编译器将尝试实例化您的函数,但如果输入参数t
没有成员函数dump
,它将不会发出错误,而是会考虑它因为替换失败,因此它不会实例化模板。