c++ - SFINAE 以返回类型工作,但不作为模板参数

标签 c++ templates c++11 sfinae

我已经用过很多次 SFINAE 成语了,我习惯了把我的 std::enable_if<>在模板参数中而不是在返回类型中。但是,我遇到了一些它不起作用的琐碎案例,我不知道为什么。首先,这是我的主要内容:

int main()
{
    foo(5);
    foo(3.4);
}

这里是 foo 的实现触发错误:

template<typename T,
         typename = typename std::enable_if<std::is_integral<T>::value>::type>
auto foo(T)
    -> void
{
    std::cout << "I'm an integer!\n";
}

template<typename T,
         typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
auto foo(T)
    -> void
{
    std::cout << "I'm a floating point number!\n";
}

这里有一段据说可以正常工作的等效代码:

template<typename T>
auto foo(T)
    -> typename std::enable_if<std::is_integral<T>::value>::type
{
    std::cout << "I'm an integrer!\n";
}

template<typename T>
auto foo(T)
    -> typename std::enable_if<std::is_floating_point<T>::value>::type
{
    std::cout << "I'm a floating point number!\n";
}

我的问题是:为什么 foo 的第一个实现触发了那个错误,而第二个没有触发它?

main.cpp:14:6: error: redefinition of 'template<class T, class> void foo(T)'
 auto foo(T)
      ^
main.cpp:6:6: note: 'template<class T, class> void foo(T)' previously declared here
 auto foo(T)
      ^
main.cpp: In function 'int main()':
main.cpp:23:12: error: no matching function for call to 'foo(double)'
     foo(3.4);
            ^
main.cpp:6:6: note: candidate: template<class T, class> void foo(T)
 auto foo(T)
      ^
main.cpp:6:6: note:   template argument deduction/substitution failed:
main.cpp:5:10: error: no type named 'type' in 'struct std::enable_if<false, void>'
          typename = typename std::enable_if<std::is_integral<T>::value>::type>
          ^

编辑:

Working codefaulty code .

最佳答案

您应该查看定义函数模板等效性的14.5.6.1 函数模板重载(C++11 标准)。简而言之,不考虑默认模板参数,因此在第一种情况下,您定义了两次相同的函数模板。在第二种情况下,您有表达式引用返回类型中使用的模板参数(再次参见 14.5.6.1/4)。由于此表达式是签名的一部分,您将获得两个不同的函数模板声明,因此 SFINAE 有机会工作。

关于c++ - SFINAE 以返回类型工作,但不作为模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15427667/

相关文章:

c++ - 如何在 C++ 中将 "convert"ISO-8859-7 字符串转换为 UTF-8?

c++ - 在 C++ (Linux) 中播放提示音

c++ - 转发模板参数

C++:无法使运算符<<成为模板化嵌套类的友元

c++ - 是否可以确定函数的参数对于可能的重载函数是有符号的还是无符号的?

multithreading - 在这种特殊情况下,C++ 11的内存顺序保证是什么?

c++ - 如何使用 "conflicting types"解决 C++/C 编译期间的 `python setup.py build` 错误?

c++ - 有没有办法自定义编译错误/警告消息?

c++ - 为什么我不能将模板参数传递给另一个模板?

C++ 11在缺少时提供空的非成员函数