模板参数扣除失败,sfinae[英] Template argument deduction failed, SFINAE

本文是小编为大家收集整理的关于模板参数扣除失败,sfinae的处理方法,想解了模板参数扣除失败,sfinae的问题怎么解决?模板参数扣除失败,sfinae问题的解决办法?模板参数扣除失败,sfinae问题的解决方案?那么可以参考本文帮助大家快速定位并解决问题,译文如有不准确的地方,大家可以切到English参考源文内容。

问题描述

当我编译此代码时:

#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;
}

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);
           ^

我还尝试了MSVC 2013.

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

live demo

推荐答案

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

do_stuff<int>(i);

一个更好的选择是将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) {}

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

do_stuff(i);

其他推荐答案

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

由于nested-name-specifier的模板参数扣除失败,因此是非卵子上下文.

Nested-Name Pesifier(示波器分辨率运算符的所有内容::)使用合格的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>

其他推荐答案

编译器尝试解决do_stuff(int&)时,它看到编译器告诉您的两个候选人.但是,找不到满足std::enable_if_t<std::is_integral<T>::value, T> == int的T,也无法找到满足std::enable_if_t<std::is_class<T>::value, T> == int的T.

tartanllama的答案,避免这种情况的方法是使参数可推论(例如do_stuff(T&)),并制作 return类型或a 后续模板参数依赖于T.

本文地址:https://www.itbaoku.cn/post/2361183.html

问题描述

When I compile this code:

#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;
}

GCC says:

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);
           ^

I've also tried on msvc 2013.

Why do I get these errors?

Live Demo

推荐答案

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.

查看更多