0

There are two form of the c++ function std::make_any,

template< class T, class... Args > std::any make_any( Args&&... args ); (1) template< class T, class U, class... Args > std::any make_any( std::initializer_list<U> il, Args&&... args ); (2) 

How does the second form work? Why it is not just

template< class T, class U> std::any make_any( std::initializer_list<U> il) ? 

For example, in this statement,

std::any a = std::make_any<std::list<int>>({1,2,3}). 

Or can you call it with both an initializer_list and together with some other arguments, such as, {1,2,3}, 4,5? Is the args here for constructing il, or for list?

1 Answer 1

2

The reason this second for exists is due to std::initializer_list not playing well with template argument deduction. Imagine you own implementation (using std::make_any as an implementation) that does not offer the second form;

template< class T, class... Args > std::any poor_make_any(Args&&... args) { return std::make_any<T>(std::forward<Args>(args)...); } 

This works well for e.g.

struct Test { Test(std::initializer_list<int>) {} Test(int) {} }; std::any x = poor_make_any<Test>(42); 

but it fails to compile for

std::any x = poor_make_any<Test>({1, 2, 3}); 

again because std::initializer_list<int> cannot be deduced by the compiler. While you can always specify the second template argument, this is overly verbose for a function from the make_ family that is meant to be a deduction helper.

And finally, the remaining arguments are just additional flexibility that you get for free. Imagine this additional constructor for the Test example,

Test(std::initializer_list<int>, int) {} 

It just works with

std::any x = std::make_any<Test>({1,2,3}, 42); 

While if that variadic second part wasn't there, you had to

std::any x = std::make_any<Test, std::initializer_list<int>, int>({1,2,3}, 42); 

which is obviously not super convenient.

Sign up to request clarification or add additional context in comments.

2 Comments

You made it very clear, thanks! Now I understood it that, here, "std::initializer_list<U> il" is just for the first parameter for constructor of 'T'; and args could have zero or more to follow.
It's by the way a good question IMHO. Not sure where the downvote came from, maybe the missing formatting in the first version.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.