Template argument deduction failed, SFINAE

若如初见. 提交于 2019-12-06 04:49:15

As the compiler says, that parameter type is non-deducible, so you would need to supply the template argument manually, like this:

do_stuff<int>(i);

A better option is to put the std::enable_if in the return type or template parameter list:

//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) {}

This way the template parameter can still be deduced:

do_stuff(i);

Why do I get these errors?

Because template argument deduction fails for nested-name-specifier, which is non-deduced contexts.

The nested-name-specifier (everything to the left of the scope resolution operator ::) of a type that was specified using a qualified-id.

// the identity template, often used to exclude specific arguments from deduction
template<typename T> struct identity { typedef T type; };
template<typename T> void bad(std::vector<T> x, T value = 1);
template<typename T> void good(std::vector<T> x, typename identity<T>::type value = 1);
std::vector<std::complex<double>> x;
bad(x, 1.2);  // P1 = std::vector<T>, A1 = std::vector<std::complex<double>>
              // P1/A1: deduced T = std::complex<double>
              // P2 = T, A2 = double
              // P2/A2: deduced T = double
              // error: deduction fails, T is ambiguous
good(x, 1.2); // P1 = std::vector<T>, A1 = std::vector<std::complex<double>>
              // P1/A1: deduced T = std::complex<double>
              // P2 = identity<T>::type, A2 = double
              // P2/A2: uses T deduced by P1/A1 because T is to the left of :: in P2
              // OK: T = std::complex<double>

When the compiler tries to resolve do_stuff(int&), it sees the two candidates that the compiler tells you about. But it's not able to "work backwards" to find a T that satisfies std::enable_if_t<std::is_integral<T>::value, T> == int, nor to find a T that satisfies std::enable_if_t<std::is_class<T>::value, T> == int.

As mentioned in TartanLlama's answer, the way to avoid this is to make the argument deducible (e.g. do_stuff(T&)) and make the return type or a subsequent template argument dependent on T.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!