【问题标题】:Single template parameter pack for multiple variadic functions?多个可变参数函数的单个模板参数包?
【发布时间】:2019-12-11 13:23:49
【问题描述】:

通常我们会做这样的事情来定义多个采用相同参数包的可变参数函数:

template<typename ...Pack>
void func1(Pack... params);

template<typename ...Pack>
void func2(Pack... params);

template<typename ...Pack>
void func3(Pack... params);

template<typename ...Pack>
void func4(Pack... params);

有没有办法避免这种多余的重复?例如,类似:

template<typename ...Pack>
{
    void func1(Pack... params);
    void func2(Pack... params);
    void func3(Pack... params);
    void func4(Pack... params);
}

【问题讨论】:

  • 这是为了避免打字还是您真的需要采用相同(与相同类型)参数包的函数?
  • 您是否将此参数包限制为某些类型的子集或参数数量?如果不是,为什么这是个问题?
  • @DanielJour 后者。每个可变参数函数中的所有参数都将具有完全相同的类型——只有一种类型。
  • @MarekR 对不起,我不明白你的反对意见。
  • 只是我(可能还有其他人)不明白什么是收益/目标。是否只是为了在定义此模板时为您节省打字?它对模板的使用方式有影响吗?

标签: c++ templates variadic-templates


【解决方案1】:

Pre C++20 答案:不,您无法做任何事情来获得这样的语法。您能做的最好的事情就是创建一个为您完成大量工作的宏。

C++20:您可以将auto 用于函数参数类型,它是用于编写模板的语法糖,就像当前用于 lambda 一样。那会给你

void func1(auto... params);
void func2(auto... params);
void func3(auto... params);
void func4(auto... params);

【讨论】:

    【解决方案2】:

    如果你可以使用 C++17...也许你可以定义一个函数,附加一个模板参数,即函数的编号,并使用if constexpr 分隔单个函数的主体。

    我的意思如下

    template <int Id, typename ... Pack>
    void func (Pack ... params)
     {
       if constexpr ( 1 == id )
        { /* body of func1() */ }
       else if constexpr ( 2 == id )
        { /* body of func2() */ }
       else if constexpr ( 3 == id )
        { /* body of func3() */ }
       // else // etc...
     }
    

    调用func()你必须明确整数模板参数

    func<1>("abc"); // equivalent to func1("abc");
    

    正如 Nathan Oliver 所观察到的,当函数的名称很重要且具有描述性(而不是简单的枚举)时,使用整数模板参数会给您带来松散的描述。

    在这种情况下,您可以添加枚举值附加模板参数,而不是 int。带有枚举值的描述​​性名称。

    有点像

    enum funcId
     {
       a_complex_and_descriptive_func_id,
       another_complex_func_id,
       a_third_complex_func_id // , etc...
     }     
    
    template <funcId Id, typename ... Pack>
    void func (Pack ... params)
     {
       if constexpr ( a_complex_and_descriptive_func_id == id )
        { /* body of first function */ }
       else if constexpr ( another_complex_func_id == id )
        { /* body of second function */ }
       else if constexpr ( a_third_complex_func_id == id )
        { /* body of third function */ }
       // else // etc...
     }
    

    电话变成了

    func<a_complex_and_descriptive_func_id>("abc");
    

    【讨论】:

    • 现在你必须记住一个函数的数字,而不是一个很好的描述性函数名称。
    • @NathanOliver-ReinstateMonica - 好吧...如果描述性函数名称是func1func2func3,我认为这不会更糟。如果名称真的是描述性的......而不是整数,我想附加的模板参数可以是具有描述性值的枚举。
    • 我感觉 func1, func2, ..., 只是 OP 的占位符名称
    • @NathanOliver-ReinstateMonica - 我想你的感觉是正确的。改进了答案以显示enum(详细和描述性)替代方案。
    【解决方案3】:

    尝试将它们包装在结构中。如果您希望它们独立于任何对象状态,则应将它们声明为静态。

    template <typename ...Pack>
    struct FunctionHolder
    {
        static void func1(Pack... params);
    
        static void func2(Pack... params);
    };
    

    LIVE SAMPLE

    【讨论】:

    • 不过不再推断了。
    猜你喜欢
    • 1970-01-01
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多