模板参数推导失败,SFINAE
Template argument deduction failed, 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;
}
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。
为什么我会出现这些错误?
实时演示
正如编译器所说,该参数类型是不可推导的,因此您需要手动提供模板参数,如下所示:
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);
为什么我会出现这些错误?
因为嵌套名称说明符是非推导上下文,模板参数推导失败。
使用限定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&)
),并使返回类型或后续模板参数依赖于T
。
相关文章:
- 如果没有malloc,链表实现将失败
- 模板参数替换失败,并且未完成隐式转换
- 构造函数SFINAE和继承在clang中失败
- C++ 带有 decltype 的 SFINAE:替换失败成为错误?
- SFINAE - 如果更复杂的功能失败,则回退到默认功能
- MSVC SFINAE:替代不会失败
- 在模板参数中评估 constexpr 时 SFINAE 失败
- SFINAE 序列化共享指针失败
- 使用ENABLE_IF和SFINAE时,功能参数类型扣除(std容器,例如向量)失败
- SFINAE使用演绎,但用替换失败
- Sfinae 类型特征会自动扣除失败
- 模板参数推导失败,SFINAE
- 类模板中的 typedef 的 SFINAE 失败是指另一个类模板中的 typedef
- 变量args SFINAE默认构造函数在clang中工作,但在Visual Studio 2015中失败
- is_container trait在std::set SFINAE问题上失败
- 是否有一种方法可以使用SFINAE来确定对模板化函数的调用是否会由于所提供的类型而失败
- 替换失败不是static_cast的错误(SFINAE)问题
- C++为什么 SFINAE 仅使用类模板参数会失败
- 在存在泛型构造函数的情况下,对三元运算符的SFINAE失败
- 带有继承历史的CRTP插件自动注册(尝试使用SFINAE,但失败)