一个函数具有可变数量的参数与已知类型,c ++ 11方式 [英] A function with variable number of arguments with known types, the c++11 way

查看:154
本文介绍了一个函数具有可变数量的参数与已知类型,c ++ 11方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经知道 stdarg.h 方法可以在c ++中使用变量参数的函数这里
我也知道c ++ 11标准有可变参数模板,这里



但是在上述两种方案中,我们不知道(我们不能强制)在编译时afaik的参数类型。我正在寻找的是传递已知类型的变量参数到函数。我认为这是可以做到的,因为我阅读了这里


Variadic模板,也可以用来创建函数采用可变数量的参数,通常是更好的选择,因为它们不强制限制参数的类型,do不执行积分和浮点促销,并且是类型安全。


有可能吗?

解决方案

这是直接使用可变参数模板编写函数,接受任意参数个数。与一般模式的唯一区别是,具体类型用作第一个参数(头),而不是模板参数。以下示例显示一个函数 foobar ,它接受任意数量的字符串。

  //用于递归结束 - 和空参数列表
void foobar(){}

template< typename ... Tail>
void foobar(const std :: string& head,Tail&& ... tail)
{
//执行头部
std :: cout< ;头<< '\\\
';
//使用剩余的参数递归调用foobar
foobar(std :: forward< Tail>(tail)...);
}

foobar(Hello,World,...);

就个人而言,我更喜欢使用 std :: initializer_list 而不是可变参数模板。因为可变参数模板更复杂,需要额外的经验。使用 std :: initializer_list ,它可能如下所示:

  foob​​ar(std :: initializer_list< std :: string> values)
{
for(auto& value:values){
//做某些值为
std :: cout <<值<< '\\\
';
}
}

foobar({Hello,World,...,});不幸的是,当使用 std :: initializer_list

时,需要额外的大括号。 / code>具有常规函数。



编辑:根据反馈重写答案。特别是我改变了两个解决方案/示例的顺序。


I already know the stdarg.h way to have a function with variable arguments in c++ as discussed here for example. I also know c++11 standard has variadic templates as explained here.

But in both of aforementioned schemes we don't know (and we can't force) argument types in compile time afaik. What I'm looking for is to pass variable arguments of known types to a function. I think this can be done because I read about it here:

Variadic templates, which can also be used to create functions that take variable number of arguments, are often the better choice because they do not impose restrictions on the types of the arguments, do not perform integral and floating-point promotions, and are type safe.

Is it possible? If yes, how can I do this?

解决方案

It is straight forward to write a function with variadic templates, that accept an arbitrary number of arguments. The only difference to the general pattern is, that a concrete type is used as first argument (head) - instead of a template parameter. The following example shows a function foobar, that accepts an arbitrary number of strings.

// used for end of recursion - and for the empty arguments list
void foobar() { }

template <typename ...Tail>
void foobar(const std::string& head, Tail&&... tail)
{
    // do something with head
    std::cout << head << '\n';
    // call foobar recursively with remaining arguments
    foobar(std::forward<Tail>(tail)...);
}

foobar("Hello", "World", "...");

Personally, I prefer using std::initializer_list instead of variadic templates. Because variadic templates are more complex and require additional experience. With std::initializer_list, it might look like this:

void foobar(std::initializer_list<std::string> values)
{
    for (auto& value : values) {
        // do something with value
        std::cout << value << '\n';
    }
}

foobar({ "Hello", "World", "...", });

Unfortunately, the additional curly braces are required when using std::initializer_list with regular functions. They are not required for constructors, if the new initializer syntax is used.

Edit: Rewrote the answer according to the feedback. In particular I have changed the order of the two solutions/examples.

这篇关于一个函数具有可变数量的参数与已知类型,c ++ 11方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆