如何结合Concept与Requires实现模板类的偏特化?
用C++ Concepts实现模板类偏特化的正确姿势
你之前的写法错误在于混淆了模板函数重载和模板类偏特化的语法——类模板不能像函数那样直接用Concept"重载",必须基于主模板来写偏特化版本,不能定义多个主模板。
错误原因分析
你写的两段代码本质都是重复定义了主模板:
- 第一段里,先写了
template <typename T> class Test {};主模板,之后又写template <Integral T> class Test {};,这不是偏特化,是重新定义了一个新的主模板,编译器会报重复定义错误。 - 第二段里的两个
template <Concept T> class Test {};也都是主模板,同样会因为重复定义报错。
正确写法示例
方式1:用Concept直接约束偏特化的模板参数
#include <type_traits> #include <iostream> template <typename T> concept Integral = std::is_integral_v<T>; template <typename T> concept IsNotIntegral = !std::is_integral_v<T>; // 第一步:先定义主模板 template <typename T> class Test { public: Test() { std::cout << "主模板实例化\n"; } }; // 针对满足Integral约束的T做偏特化 template <Integral T> class Test<T> { // 注意这里的<T>,表示这是对主模板Test<T>的偏特化 public: Test() { std::cout << "整数类型偏特化实例化\n"; } }; // 针对满足IsNotIntegral约束的T做偏特化 template <IsNotIntegral T> class Test<T> { public: Test() { std::cout << "非整数类型偏特化实例化\n"; } }; int main() { Test<int> t_int; // 输出:整数类型偏特化实例化 Test<double> t_double; // 输出:非整数类型偏特化实例化 Test<char> t_char; // 输出:整数类型偏特化实例化 return 0; }
方式2:用requires子句约束偏特化
如果更喜欢用requires子句,也可以这么写:
// 主模板不变 template <typename T> class Test { public: Test() { std::cout << "主模板实例化\n"; } }; // 用requires子句指定偏特化的约束 template <typename T> requires Integral<T> class Test<T> { public: Test() { std::cout << "整数类型偏特化实例化\n"; } }; template <typename T> requires IsNotIntegral<T> class Test<T> { public: Test() { std::cout << "非整数类型偏特化实例化\n"; } };
核心要点
- 必须先定义主模板,所有偏特化版本都是基于主模板的扩展,不能跳过主模板直接写带约束的类模板。
- 偏特化的语法必须带
<T>(或对应模板参数),比如class Test<T>,用来明确这是对主模板Test<T>的特化。 - Concept既可以直接作为模板参数的约束,也可以通过requires子句添加,两种写法效果一致,选自己习惯的即可。
内容的提问来源于stack exchange,提问作者shengguo lu
相关产品推荐
相关产品推荐

