完美转发,可变模板,initializer_list - 在一起 [英] perfect forwarding, variadic template, initializer_list - together
问题描述
gcc 4.8.1& clang 3.3,c ++ 11特性完成,
我需要在一些函数中转发args,这些函数构建像make_shared / c ++ 14 make_unique这样的元素。但我有类型推演/转发初始化列表/数组的问题
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
我需要工作的例子 foo * foo3 {make_it< foo> 1,1},{10,10}},10)};
,因此 std :: initializer_list
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;
}
实际上foo3将会失败,clang 3.3:
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.
并使用gcc 4.8.1:
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
推荐答案
统一初始化不适用于转发。您不能转发初始化参数(直接),然后使用这些初始化某些对象。您可以初始化函数的参数,然后将其转发给其他人,但不能转发初始化参数。
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 {}
stuff)不参与模板参数扣除。这就是为什么你的 foo3
得到一个错误,当你这样做。编译器不能知道你想要它转换成什么类型,所以它失败。
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.
即使你试图存储 {{1,1 },{10,10}}
在一个 auto
变量,你不会得到你想要的。 auto
可以将支持初始化列表类型推导到 initializer_list
类型,但是你会得到类似 initializer_list< initializer_list< int>>
。
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.
这篇关于完美转发,可变模板,initializer_list - 在一起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!