perfect forwarding, variadic template, initializer_list - together
c++11
Solution
Uniform initialization does not work with forwarding. You can't forward initialization parameters (directly) and then use those to initialize some object. You can initialize a parameter of a function and then forward that along to someone else, but you can't forward initialization parameters.
Braced-init-lists (aka: the `{}` stuff) do not participate in template argument deduction. That's why your `foo3` gets an error when you do it. The compiler can't know what type you want it converted into, so it fails.
Even if you tried to store `{{1, 1}, {10, 10}}` in an `auto` variable, you wouldn't get what you want. `auto` can type-deduce braced-init-lists into `initializer_list` types, but you'd get something like `initializer_list<initializer_list<int>>`.
The compiler simply is not going to go through your template code and figure out what type you really meant.
Problem
gcc 4.8.1 & clang 3.3, c++11 feature complete, I need to forward args in some function that constructs elements like make_shared/c++14 make_unique. But I have problem with type deduction/forwarding initializer lists/arrays I need working example of `foo * foo3{ make_it<foo>( {{1,1},{ 10,10 }}, 10 ) };`, so `std::initializer_list` will deduce it arguments and function will forward them ``` #include <initializer_list> #include <algorithm> struct foo { struct pairs{ int a,b; }; foo( int value ){} foo( std::initializer_list<pairs> elems, int value ){} }; //some custom allocation mechanizm char store[sizeof(foo)*2]; char * store_ptr = &store[0]; void * allocfromstore( size_t sz ) { void * ret = store_ptr; store_ptr+= sz; return ret; } template<typename ValueType, typename ArrType, typename... Args> ValueType * make_it(std::initializer_list<ArrType> il, Args&&... args) { ValueType * obj = new (allocfromstore(sizeof(ValueType))) ValueType( il, std::forward<Args>(args)...); return obj; } template<typename ValueType, typename... Args> ValueType * make_it(Args&&... args) { ValueType * obj = new (allocfromstore(sizeof(ValueType))) ValueType( std::forward<Args>(args)...); return obj; } std::initializer_list<foo::pairs> encapsulate( std::initializer_list<foo::pairs> il ){ return il; } int main(){ foo * foo0{ make_it<foo>( 10 ) }; foo * foo1{ make_it<foo>( std::initializer_list<foo::pairs>({{1,1},{ 10,10 }}), 10 ) }; foo * foo2{ make_it<foo>( encapsulate({{1,1},{ 10,10 }}), 10 ) }; foo * foo3{ make_it<foo>( {{1,1},{ 10,10 }}, 10 ) }; return 0; } ``` actually foo3 will fail with clang 3.3: ``` test.cpp:37:15: error: no matching function for call to 'make_it' foo * foo3{ make_it<foo>( {{1,1},{ 10,10 }}, 10 ) }; ^~~~~~~~~~~~ test.cpp:18:13: note: candidate template ignored: couldn't infer template argument 'ArrType' ValueType * make_it(std::initializer_list<ArrType> il, Args&&... args) ^ test.cpp:26:13: note: candidate function not viable: requires 0 arguments, but 2 were provided ValueType * make_it(Args&&... args) ^ 1 error generated. ``` and with gcc 4.8.1: ``` test.cpp: In function ‘int main()’: test.cpp:37:51: error: no matching function for call to ‘make_it(<brace-enclosed initializer list>, int)’ foo * foo3{ make_it<foo>( {{1,1},{ 10,10 }}, 10 ) }; ^ test.cpp:37:51: note: candidates are: test.cpp:18:13: note: template<class ValueType, class ArrType, class ... Args> ValueType* make_it(std::initializer_list<ArrType>, Args&& ...) ValueType * make_it(std::initializer_list<ArrType> il, Args&&... args) ^ test.cpp:18:13: note: template argument deduction/substitution failed: test.cpp:37:51: note: couldn't deduce template parameter ‘ArrType’ foo * foo3{ make_it<foo>( {{1,1},{ 10,10 }}, 10 ) }; ^ test.cpp:26:13: note: ValueType* make_it(Args&& ...) [with ValueType = foo; Args = {}] ValueType * make_it(Args&&... args) ^ test.cpp:26:13: note: candidate expects 0 arguments, 2 provided ```