考虑这两个功能:
template <class Type,
class = typename std::enable_if</*HAS OPERATOR <<*/>::type>
void f(std::ostream& stream, const Type& value);
template <class Type,
class... DummyTypes,
class = typename std::enable_if<sizeof...(DummyTypes) == 0>::type>
void f(std::ostream& stream, const Type& value, DummyTypes...);
由于非可变重载优先于可变参数重载,我想在第一个版本中使用operator<<
检查类型是否std::ostream
std::enable_if
。{ / p>
那么我应该写什么而不是/*HAS OPERATOR <<*/
?
答案 0 :(得分:6)
以下内容应该有效
template <class Type,
class = decltype(std::declval<std::ostream&>() << std::declval<Type>())>
void f(std::ostream& stream, const Type& value)
{
stream << value;
}
(请注意,在这种情况下您不需要使用std::enable_if
)
答案 1 :(得分:6)
使用尾随返回类型(1),您实际上可以预先考虑概念:
template <typename Type>
auto f(std::ostream& out, Type const& t) -> decltype(out << t, void()) {
// ...
}
由于SFINAE,只有在out << t
的类型可以解析时才能选择此重载,这意味着存在接受两个参数的<<
重载。
如果您需要相反的,那么如果此重载不存在,则启用一个函数,这是一个缺陷。在这种情况下,据我所知,enable_if
策略(以及对称disable_if
)是必要的。
(1)感谢Simple帮助解决语法
答案 2 :(得分:2)
最简单的方法是检查你何时有参数,即我宁愿尝试使用这样的东西:
template <typename Type>
auto f(std::ostream& out, Type const& value)
-> typename std::enable_if<sizeof(out << value) != 0>::type {
...
}
使用std::declval()
可以获得类似的效果但是我不确定是否创建了引用。