如何编写仅接受两种支持[]运算符的C++模板函数?
C++限定模板函数仅适配两种支持[]运算符的类型
如果你需要让C模板函数只接受指定的两种支持[]运算符的类型,可以根据C版本选择不同的实现方式,以下是具体方案:
C++20及以上:使用Concepts(推荐)
C++20引入的Concepts可以像TypeScript的extends一样直观地限定模板参数类型,写法简洁且可读性强:
#include <string> #include <vector> #include <concepts> #include <type_traits> // 定义Concept,限定允许的类型为std::string或std::vector<int>(可按需修改) template<typename T> concept AllowedType = std::same_as<std::remove_cvref_t<T>, std::string> || std::same_as<std::remove_cvref_t<T>, std::vector<int>> || std::same_as<std::remove_cvref_t<T>, int[]>; // 支持原生int数组 // 应用Concept限定模板参数 template<AllowedType T> auto func(T&& arg) { return arg[0]; } // 测试示例 int main() { func(std::string("hello")); // 合法:std::string符合要求 func(std::vector<int>{1, 2, 3}); // 合法:std::vector<int>符合要求 int arr[] = {4, 5, 6}; func(arr); // 合法:原生int数组符合要求 // func(std::vector<double>{1.1, 2.2}); // 编译错误:类型不在允许列表中 // func(123); // 编译错误:int不支持[](或不在允许列表) return 0; }
AllowedType概念明确指定了模板参数必须是std::string、std::vector<int>或原生int[],不符合条件的类型会在编译阶段直接报错,和TypeScript的类型检查逻辑一致。
C++20之前:使用SFINAE与类型特性(Type Trait)
如果需要兼容C11/C17,可以借助SFINAE机制结合自定义类型特性来实现类型限定:
#include <string> #include <vector> #include <type_traits> // 自定义类型特性,默认标记为不允许的类型 template<typename T> struct is_allowed_type : std::false_type {}; // 特化:允许std::string template<> struct is_allowed_type<std::string> : std::true_type {}; // 特化:允许std::vector<int> template<> struct is_allowed_type<std::vector<int>> : std::true_type {}; // 特化:允许任意长度的原生int数组 template<std::size_t N> struct is_allowed_type<int[N]> : std::true_type {}; // 使用std::enable_if_t实现SFINAE,仅当类型符合要求时实例化模板 template<typename T, typename = std::enable_if_t<is_allowed_type<std::remove_cvref_t<T>>::value>> auto func(T&& arg) { return arg[0]; } // 测试示例 int main() { func(std::string("test")); func(std::vector<int>{10, 20}); int arr[] = {100, 200}; func(arr); // func(std::vector<float>{1.0f, 2.0f}); // 编译错误 return 0; }
这里通过is_allowed_type结构体标记允许的类型,再用std::enable_if_t在模板参数列表中做过滤——只有当类型特性为true时,模板才会被成功实例化,否则会因为SFINAE规则被编译器忽略,最终触发编译错误。
内容的提问来源于stack exchange,提问作者tannerman
相关产品推荐
相关产品推荐

