如何编写匹配任意数量size_t参数的C++ Concept?
使用C++ Concept优雅约束支持任意数量size_t参数的Policy
问题描述
我定义了依赖Policy的Bar结构体,希望用Concept对Policy进行约束。当前的FooConcept仅能匹配接收固定2个size_t参数的Policy,但逻辑上,所有包含Foo方法、接收容器+任意数量size_t参数且返回T&的Policy都应该满足约束。比如带3个size_t参数的Policy2无法通过当前校验,而临时叠加多个requires条件的方案过于繁琐,求更优雅的实现方式。
原实现代码
#include <array> #include <concepts> template<typename Policy, typename T> concept FooConcept = requires(std::array<T, 42> arr, size_t val) { { Policy::Foo(arr, val, val) } -> std::same_as<T&>; }; template<typename T, typename Policy> requires FooConcept<Policy, T> struct Bar { std::array<T, 42> arr; template<typename... Args> T& foo(Args... args) { return Policy::Foo(arr, args...); } };
符合当前约束的Policy示例
struct Policy1 { template<typename Cont> static decltype(auto) Foo(Cont& c, size_t arg1, size_t arg2) { // 处理容器c及参数arg1、arg2的逻辑 } };
逻辑上应符合但无法通过约束的Policy示例
struct Policy2 { template<typename Cont> static decltype(auto) Foo(Cont& c, size_t arg1, size_t arg2, size_t arg3) { // 处理容器c及参数arg1、arg2、arg3的逻辑 } };
Bar的使用示例
using MyFancyBar = Bar<int, Policy1>; // using MyCoolBar = Bar<int, Policy2>; // 当前会编译失败 int main() { MyFancyBar bar; // MyCoolBar bar2; std::cout << bar.foo(0, 0); // std::cout << bar2.foo(0, 1, 2); return 0; }
优雅解决方案
利用C++20的模板Concept和折叠表达式,可以一次性定义支持任意数量size_t参数的约束,无需手动叠加多个requires条件。
修改后的FooConcept
#include <array> #include <concepts> template<typename Policy, typename T> concept FooConcept = // 要求Policy::Foo能接受任意数量的size_t参数,且返回T& template<typename... Sizes> requires (std::same_as<Sizes, size_t> && ...) && requires(std::array<T, 42> arr, Sizes... sizes) { { Policy::Foo(arr, sizes...) } -> std::same_as<T&>; };
验证修改后的约束
修改后,Policy1和Policy2都能通过FooConcept校验,Bar可以正常实例化:
using MyFancyBar = Bar<int, Policy1>; using MyCoolBar = Bar<int, Policy2>; // 现在编译通过 int main() { MyFancyBar bar; MyCoolBar bar2; std::cout << bar.foo(0, 0); std::cout << bar2.foo(0, 1, 2); return 0; }
实现说明
- 模板Concept(
template<typename... Sizes>)用于匹配任意数量的参数包; - 折叠表达式
(std::same_as<Sizes, size_t> && ...)确保所有参数都是size_t类型; - 内层
requires子句验证Policy::Foo的调用合法性及返回值类型,一次定义覆盖所有数量的size_t参数场景。
内容的提问来源于stack exchange,提问作者falsekeel
相关产品推荐
相关产品推荐

