C++20中enable_if模板特化匹配异常问题咨询
C++模板匹配问题解惑
问题场景1
以下代码调用AFuncToTest<int, int8_t>()后输出"it fails!",而非预期的"int value!":
#include <iostream> #include <type_traits> template <typename T, typename E> void AFuncToTest() { std::cout << "it fails!" << std::endl; } template <typename T, std::enable_if_t<std::is_same_v<T, int8_t> || std::is_same_v<T, int16_t>>> void AFuncToTest() { std::cout << "int value!" << std::endl; } int main() { AFuncToTest<int, int8_t>(); }
输出:"it fails!"
问题场景2
修改后的代码仍得到相同结果:
#include <iostream> template <typename T, typename E> void AFuncToTest() { std::cout << "it fails!" << std::endl; } template <typename T, int8_t> void AFuncToTest() { std::cout << "int value!" << std::endl; } int main() { AFuncToTest<int, int8_t>(); }
输出:"it fails!"
核心问题:类型模板参数与非类型模板参数的混淆
两个案例的本质错误是混淆了类型模板参数和非类型模板参数:
- 类型模板参数:用
typename/class声明,调用时必须传入类型(比如int、int8_t),对应第一个模板的typename T, typename E。 - 非类型模板参数:是具体的常量值(比如整数、指针等),声明时直接写类型(比如
int8_t),调用时必须传入对应类型的常量值(比如static_cast<int8_t>(0)),而非类型本身。
场景1分析
第二个模板的第二个参数是std::enable_if_t<...>:
- 当条件为真时,
std::enable_if_t的结果是void,因此该模板的参数列表等价于typename T, void——这是一个无意义的非类型模板参数。 - 调用时传入的是两个类型参数
int和int8_t,与第二个模板的参数结构不匹配,因此只会匹配第一个模板。
场景2分析
第二个模板的第二个参数是int8_t,属于非类型模板参数,要求调用时传入int8_t类型的常量值(比如AFuncToTest<int, static_cast<int8_t>(10)>),但你传入的是类型int8_t,参数类型不匹配,因此仍然匹配第一个模板。
正确写法示例
如果想要根据模板参数的类型进行重载匹配,C++20推荐用requires约束实现:
#include <iostream> #include <type_traits> template <typename T, typename E> void AFuncToTest() { std::cout << "it fails!" << std::endl; } // 约束T为int8_t或int16_t时匹配此重载 template <typename T, typename E> requires std::is_same_v<T, int8_t> || std::is_same_v<T, int16_t> void AFuncToTest() { std::cout << "int value!" << std::endl; } int main() { AFuncToTest<int8_t, int>(); // 输出:"int value!" AFuncToTest<int, int8_t>(); // 输出:"it fails!"(T是int,不满足约束) }
如果想要约束第二个参数E为int8_t,只需修改requires条件:
template <typename T, typename E> requires std::is_same_v<E, int8_t> void AFuncToTest() { std::cout << "int value!" << std::endl; } int main() { AFuncToTest<int, int8_t>(); // 输出:"int value!" }
内容的提问来源于stack exchange,提问作者orochi
相关产品推荐
相关产品推荐

