繁体   English   中英

如何编写不带参数包的可变参数函数?

[英]How to write a variadic function without parameter pack?

假设我有一个模板

template<typename Bar>
Result foo(const Input& input);

而我却想创建一个模板foo() ,它将获取许多Bar模板参数和许多Input并将Result放在一起。

我写了一个带有输入容器的版本:

template<typename Bar>
Result foo(const std::vector<Input>& inputs);

template<typename Bar1, typename Bar2, typename ... Bars>
Result foo(const std::vector<Input>& inputs) {
    // calls foo<Bar2, Bars ...>(shorter_inputs);
}

但是,以上版本无法在编译时检查输入的长度是否与模板参数的数量匹配。 另外,我想要一个只需要输入内容而不需要容器的版本:

foo<Bar1, Bar2>(input1, input2);
// instead of
// foo<Bar1, Bar2>({input1, input2});

我试图写这样的东西

template<typename Bar1, typename Bar2, typename ... Bars>
Result bar(const Input& in1, const Input& in2, const Input& ... inputs)

被编译器拒绝,因为...仅适用于参数包。 是否可以在不使用va_args情况下用C ++编写这样的可变参数函数?

只需使用两个参数包:

template<typename Bar, typename... Bars, typename Input, typename... Inputs>
std::string foo(const Input &input, const Inputs &... inputs)
{
    std::string result(Bar::get_name());
    result.append(input);

    if constexpr (sizeof...(inputs) > 0)
        result.append(foo<Bars...>(inputs...));

    return result;
}

不知道您想要什么...

如果ResultInput是类型而不是模板参数,并且您希望模板foo()可以接收与模板对象一样多的Input对象,则可以从自定义模板参数GetFirst开始,以选择可变参数列表中的第一个模板参数

template <typename T0, typename ...>
struct GetFirst
 { using type = T0; };

并如下写foo()

template <typename ... Bars>
Result foo (typename GetFirst<Input, Bars>::type const & ... is)
 { 
   // something with is...
   return {};
 }

所以你有了

//foo<long, long long>(Input{}, Input{}, Input{}); // compilation error

foo<int, long, long long>(Input{}, Input{}, Input{}); // compiles

//foo<int, long, long long>(Input{}, Input{}); // compilation error

如果要管理单个对象is... ,则可以递归地编写foo() ,如下所示

template <typename, typename ... Bars>
Result foo (Input const & i0,
            typename GetFirst<Input, Bars>::type const & ... is)
 {
   // do something with i0

   return foo<Bars...>(is...);
 }

但是您还需要一个基本案例模板foo()来终止递归; 我提出了一个foo() ,它接收带有默认值的模板非类型参数(以在列表为空时拦截Bars...

template <int = 0>
Result foo ()
 { return {}; }

以下是一个完整的,可能很愚蠢的但正在编译的示例

struct Input  { };
struct Result { };

template <typename T0, typename ...>
struct GetFirst
 { using type = T0; };

// ground case
template <int = 0>
Result foo ()
 { return {}; }

// recursive case
template <typename, typename ... Bars>
Result foo (Input const & i0,
            typename GetFirst<Input, Bars>::type const & ... is)
 {
   // do something with i0

   return foo<Bars...>(is...);
 }

int main()
 {
   //foo<long, long long>(Input{}, Input{}, Input{}); // compilation error

   foo<int, long, long long>(Input{}, Input{}, Input{}); // compiles

   //foo<int, long, long long>(Input{}, Input{}); // compilation error
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM