SFINAE模板参数推断失败

jos*_*ray 2 c++ templates sfinae

当我编译这段代码时:

#include <type_traits>

template <typename T>
void do_stuff(std::enable_if_t<std::is_integral<T>::value, T> &t) {}

template <typename T>
void do_stuff(std::enable_if_t<std::is_class<T>::value, T> &t) {}

int main() {
    int i = 1;
    do_stuff(i);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

GCC说:

37325975.cpp: In function ‘int main()’:
37325975.cpp:11:15: error: no matching function for call to ‘do_stuff(int&)’
     do_stuff(i);
               ^
37325975.cpp:4:6: note: candidate: template<class T> void do_stuff(std::enable_if_t<std::is_integral<_Tp>::value, T>&)
 void do_stuff(std::enable_if_t<std::is_integral<T>::value, T> &t) {}
      ^
37325975.cpp:4:6: note:   template argument deduction/substitution failed:
37325975.cpp:11:15: note:   couldn't deduce template parameter ‘T’
     do_stuff(i);
               ^
37325975.cpp:7:6: note: candidate: template<class T> void do_stuff(std::enable_if_t<std::is_class<T>::value, T>&)
 void do_stuff(std::enable_if_t<std::is_class<T>::value, T> &t) {}
      ^
37325975.cpp:7:6: note:   template argument deduction/substitution failed:
37325975.cpp:11:15: note:   couldn't deduce template parameter ‘T’
     do_stuff(i);
           ^
Run Code Online (Sandbox Code Playgroud)

我也尝试过msvc 2013.

为什么我会收到这些错误?

现场演示

Tar*_*ama 9

正如编译器所说,该参数类型是不可推导的,因此您需要手动提供模板参数,如下所示:

do_stuff<int>(i);
Run Code Online (Sandbox Code Playgroud)

更好的选择是将std::enable_if返回类型或模板参数列表放入:

//Return type
template <typename T>
std::enable_if_t<std::is_integral<T>::value>
do_stuff(T &t) {}

template <typename T>
std::enable_if_t<std::is_class<T>::value> 
do_stuff(T &t) {}

//Parameter list
template <typename T, std::enable_if_t<std::is_integral<T>::value>* = nullptr>
void do_stuff(T &t) {}

template <typename T, std::enable_if_t<std::is_class<T>::value>* = nullptr > 
void do_stuff(T &t) {}
Run Code Online (Sandbox Code Playgroud)

这样仍然可以推导出模板参数:

do_stuff(i);
Run Code Online (Sandbox Code Playgroud)