You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写匹配任意数量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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 01:35:26