[英]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;
}
不知道您想要什么...
如果Result
和Input
是类型而不是模板参数,并且您希望模板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.