完美转发,可变模板,initializer_list - 在一起 [英] perfect forwarding, variadic template, initializer_list - together

查看:296
本文介绍了完美转发,可变模板,initializer_list - 在一起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

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