C++11 完美转发,可变模板,初始值设定项列表-一起

C++11 完美转发,可变模板,初始值设定项列表-一起,c++11,C++11,gcc 4.8.1和clang 3.3,c++11功能完成, 我需要在一些函数中转发参数,这些函数构造元素,如make_shared/c++14 make_unique。但是我对类型推断/转发初始值设定项列表/数组有问题 我需要foo*foo3{make_it({{1,1},{10,10},10})的工作示例,所以std::initializer\u list将推导它的参数,函数将转发它们 #include <initializer_list> #include <algori

gcc 4.8.1和clang 3.3,c++11功能完成, 我需要在一些函数中转发参数,这些函数构造元素,如make_shared/c++14 make_unique。但是我对类型推断/转发初始值设定项列表/数组有问题

我需要
foo*foo3{make_it({{1,1},{10,10},10})的工作示例,所以
std::initializer\u list
将推导它的参数,函数将转发它们

#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;
}
#包括
#包括
结构foo
{
结构对{inta,b;};
foo(int值){}
foo(std::初始值设定项\列表元素,int值){}
};
//一些自定义分配机制
字符存储[sizeof(foo)*2];
char*store_ptr=&store[0];
void*allocfromstore(size_t sz){void*ret=store_ptr;store_ptr+=sz;return ret;}
模板
ValueType*make_it(std::initializer_list il,Args&…Args)
{
ValueType*obj=new(allocfromstore(sizeof(ValueType)))ValueType(il,std::forward(args)…);
返回obj;
}
模板
ValueType*make_it(Args&&…Args)
{
ValueType*obj=new(allocfromstore(sizeof(ValueType)))ValueType(std::forward(args)…);
返回obj;
}
std::initializer_list封装(std::initializer_list il){return il;}
int main(){
foo*foo0{make_it(10)};
foo*foo1{make_it(std::initializer_list({1,1},{10,10}),10)};
foo*foo2{make_it(封装({1,1},{10,10}),10};
foo*foo3{make_it({1,1},{10,10},10});
返回0;
}
实际上,foo3将因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.
test.cpp:37:15:错误:调用“make_it”时没有匹配函数
foo*foo3{make_it({1,1},{10,10},10});
^~~~~~~~~~~~
test.cpp:18:13:注意:已忽略候选模板:无法推断模板参数“ArrType”
ValueType*make_it(std::initializer_list il,Args&…Args)
^
test.cpp:26:13:注意:候选函数不可行:需要0个参数,但提供了2个
ValueType*make_it(Args&&…Args)
^
生成1个错误。
根据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
test.cpp:在函数“int main()”中:
test.cpp:37:51:错误:调用“make_it(,int)”时没有匹配函数
foo*foo3{make_it({1,1},{10,10},10});
^
考试。cpp:37:51:注:考生为:
test.cpp:18:13:注意:模板值类型*生成(std::initializer\u list,Args&&…)
ValueType*make_it(std::initializer_list il,Args&…Args)
^
test.cpp:18:13:注意:模板参数扣除/替换失败:
test.cpp:37:51:注意:无法推断模板参数“ArrType”
foo*foo3{make_it({1,1},{10,10},10});
^
test.cpp:26:13:注意:ValueType*生成它(Args&&…[其中ValueType=foo;Args={}]
ValueType*make_it(Args&&…Args)
^
test.cpp:26:13:注意:候选者需要0个参数,提供2个参数

统一初始化不适用于转发。您不能(直接)转发初始化参数,然后使用这些参数初始化某些对象。可以初始化函数的参数,然后将其转发给其他人,但不能转发初始化参数

带括号的init列表(aka:the
{}
stuff)不参与模板参数推导。这就是为什么您的
foo3
在执行此操作时会出错的原因。编译器无法知道要将其转换为什么类型,因此失败

即使您试图将
{{1,1},{10,10}}
存储在
auto
变量中,也不会得到您想要的
auto
可以将带括号的init列表类型推断为
initializer\u list
类型,但您会得到类似
initializer\u list
的内容


编译器根本不会检查您的模板代码并找出您真正想要的类型。

是一种仅适用于
foo::pairs
列表的解决方案吗

template<typename ValueType, typename... Args>
ValueType * make_it(std::initializer_list<foo::pairs> il, Args&&... args)
{
  ValueType * obj = new (allocfromstore(sizeof(ValueType))) ValueType( il, std::forward<Args>(args)...);
  return obj;
}
模板
ValueType*make_it(std::initializer_list il,Args&…Args)
{
ValueType*obj=new(allocfromstore(sizeof(ValueType)))ValueType(il,std::forward(args)…);
返回obj;
}

谢谢,我知道这一个,我想知道参数std::initializer list的推导是否可以将未命名的结构作为参数使用。但我想知道为什么它不能与未命名的结构一起使用,特别是构造函数的工作方式。初始值设定项_list@ArturBac编译器无法判断
{0,0},{1,1}}
std::initializer\u list
,还是
std::initializer\u list
,还是
std::initializer\u list
,是的,我知道它无法确定它是结构,所以它是完美转发逻辑中的一个漏洞,我被设计来为构造函数转发参数,在某些情况下它不能被使用。如果我们告诉编译器名为struct(足够只命名列表中的第一个struct):foo*foo3{make_it({foo::pairs{1,1},{10,10},10})@ArturBac:“所以这是完美转发逻辑中的一个漏洞”完美转发指的是转发对象。大括号的init列表不是对象;它是一个对象的初始值设定项,但在构造某个对象之前,它不是一个对象。“只命名列表中的第一个结构就足够了”,它假设带括号的init列表只能用于事物列表。它们的用途远不止这些。