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

如何在C++20中从花括号初始化列表推导参数包实现模板简写?

问题解决:C++20下实现Foo<{1,2,3},{4,5,6}>的简写形式

核心需求

已在FooDom命名空间实现合法的FooImp<Aux<int...>, Aux<int...>>(要求两个int...参数包长度相同),希望用Foo<{1,2,3},{4,5,6}>替代冗长的FooDom::FooImp<FooDom::Aux<1,2,3>, FooDom::Aux<4,5,6>>,且必须符合C++20标准。

已尝试方案的问题

  1. using别名定义:

    template<int ...u, int ...v>
    using Foo<{u...},{v...}> = FooDom::FooImp< FooDom::Aux<u...>, FooDom::Aux<v...> >;
    

    G12.2.0(-std=c++20)编译报错:error: template parameters not deducible in partial specialization: note:'u' note:'v',本质是C标准不允许用花括号列表作为模板别名的模板参数形式。

  2. 继承方式:

    template<auto,auto> class Foo;
    
    template<int ...u, int ...v>
    class Foo<{u...},{v...}>: public FooDom::FooImp< FooDom::Aux<u...>, FooDom::Aux<v...> >{};
    

    auto{}不符合C++20标准,即使切换到-std=c++2b,仍会因模板参数无法推导报错——花括号列表不是可推导的模板实参类型。

合规解决方案

C++20中无法直接将花括号列表作为模板参数传递,但可以通过中间类型包装参数包实现类似简写效果,以下是两种可行方案:

方案1:借助std::integer_sequence

利用C++14引入的std::integer_sequence作为参数包载体,配合模板别名+宏简化调用:

#include <utility>

namespace FooDom{
   template<int...> struct Aux{};
   template<typename,typename> class FooImp;
};

// 主模板占位
template<typename Seq1, typename Seq2>
using Foo = FooDom::FooImp<FooDom::Aux<>, FooDom::Aux<>>;

// 针对整数序列的特化
template<int... U, int... V>
using Foo<std::integer_sequence<int, U...>, std::integer_sequence<int, V...>> = 
    FooDom::FooImp<FooDom::Aux<U...>, FooDom::Aux<V...>>;

// 辅助宏进一步简化书写
#define FOO(SEQ1, SEQ2) Foo<std::integer_sequence<int, SEQ1>, std::integer_sequence<int, SEQ2>>

// 使用示例
int main() {
    FOO(1,2,3, 4,5,6) foo; // 等价于FooDom::FooImp<FooDom::Aux<1,2,3>, FooDom::Aux<4,5,6>>
}

该方案完全符合C++20标准,通过标准库类型包装参数包,宏则抹平了额外的语法层。

方案2:自定义参数包包装器+推导指引

自定义模板包装参数包,配合C++17类模板推导指引实现类对象的简写初始化:

namespace FooDom{
   template<int...> struct Aux{};
   template<typename,typename> class FooImp;
};

// 自定义整数参数包包装器
template<int... Ts>
struct IntPack {};

// Foo主模板
template<typename Pack1, typename Pack2>
class Foo;

// 特化版本,继承目标类
template<int... U, int... V>
class Foo<IntPack<U...>, IntPack<V...>> : public FooDom::FooImp<FooDom::Aux<U...>, FooDom::Aux<V...>> {};

// 推导指引,支持通过IntPack对象推导模板参数
template<int... U, int... V>
Foo(IntPack<U...>, IntPack<V...>) -> Foo<IntPack<U...>, IntPack<V...>>;

// 使用示例
int main() {
    Foo foo{IntPack<1,2,3>{}, IntPack<4,5,6>{}}; // 等价目标类型
    // 配合宏简化
#define MAKE_FOO(SEQ1, SEQ2) Foo(IntPack<SEQ1>{}, IntPack<SEQ2>{})
    auto foo2 = MAKE_FOO(1,2,3, 4,5,6);
}

此方案通过自定义模板包装参数包,推导指引让编译器能从初始化对象中推导模板参数,写法更贴近类的直观使用。

关键说明

C++标准中,花括号列表(braced-init-list)本身不是一个类型,无法直接作为模板实参传递。所有试图直接写Foo<{1,2,3},{4,5,6}>的写法都不符合标准,必须通过中间类型(如std::integer_sequence或自定义IntPack)包装参数包,才能实现合规的简写。

内容的提问来源于stack exchange,提问作者mhawth36

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:09:59