Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
204 views
in Technique[技术] by (71.8m points)

c++ - A function with variable number of arguments with known types, the c++11 way

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 << '
';
    // 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 << '
';
    }
}

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...