如何为模板参数包施加约束?
如何为模板参数包施加约束?
我来帮你一步步解决这个模板参数包的约束问题,分两种场景说明:
一、普通类型参数包的约束(Foo类场景)
如果你的模板参数包是普通类型(比如SomeTypes...是各种类/基础类型),在C++20及以后,可以直接用Concepts来约束所有类型满足std::movable,有两种常用写法:
写法1:直接在参数列表中使用Concept
这种方式最简洁,直接把std::movable作为参数的约束:
#include <concepts> template <std::movable... SomeTypes> class Foo { // 你的类实现代码 };
写法2:用requires子句配合折叠表达式
如果你需要更灵活的约束逻辑(比如多个条件组合),可以用requires加上折叠表达式,确保参数包中每一个类型都满足std::movable:
#include <concepts> template <class... SomeTypes> requires (std::movable<SomeTypes> && ...) class Foo { // 你的类实现代码 };
两种写法效果完全一致,都会在编译时检查所有SomeTypes中的类型是否可移动,不满足的话会直接报错。
二、模板模板参数包的约束(Bar类场景)
当参数包是模板模板参数(比如SomeTypes...是一个个单参数模板),约束方式需要调整——因为模板本身不是类型,我们需要通过实例化模板得到类型来做检查。
举个例子,假设我们要确保每个SomeTypes模板实例化后的类型(比如用int作为模板参数)满足std::movable,可以这样写:
写法1:自定义Concept约束模板
先定义一个Concept来描述“实例化后类型可移动的模板”,再用它约束参数包:
#include <concepts> // 定义Concept:检查模板Template实例化int后是否是可移动类型 template <template<typename> class Template> concept MovableGeneratingTemplate = std::movable<Template<int>>; // 用这个Concept约束参数包 template <MovableGeneratingTemplate... SomeTypes> class Bar { // 你的类实现代码 };
写法2:直接用requires折叠表达式
如果不需要复用这个约束,也可以直接在模板声明里写requires子句:
#include <concepts> template <template<typename> class... SomeTypes> requires (std::movable<SomeTypes<int>> && ...) class Bar { // 你的类实现代码 };
如果你的需求是“模板实例化任意合法类型T时都满足std::movable”,可以把Concept改成更通用的形式:
template <template<typename> class Template> concept AlwaysMovableTemplate = requires { // 确保对多种常见类型实例化后都满足可移动 requires std::movable<Template<int>>; requires std::movable<Template<std::string>>; // 可按需添加更多测试类型 };
备注:内容来源于stack exchange,提问作者Rob W.
相关产品推荐
相关产品推荐

