SFINAE过载选择是否有运算符&lt; <! - ? - >

时间:2013-10-06 17:11:17

标签: c++ c++11 operators sfinae enable-if

考虑这两个功能:

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 <<*/

3 个答案:

答案 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()可以获得类似的效果但是我不确定是否创建了引用。