我有一个类,其构造函数采用 initializer_list
:
Foo::Foo(std::initializer_list<Bar*> bars)
如果我尝试用大括号括起来的初始化列表直接创建一个对象,initializer_list
正确推导:
Foo f ({ &b }); // std::initializer_list<Bar*> correctly deduced
但是,当尝试间接 执行相同操作时(使用可变函数模板 - 在本例中为 make_unique
),编译器无法推断出 initializer_list
:
std::make_unique<Foo>({ &b }); // std::initializer_list<Bar*> not deduced
错误输出:
error: no matching function for call to
‘make_unique(<brace-enclosed initializer list>)’
问题:
- 为什么编译器无法推断出
{ &b }
作为initializer_list<Boo*>
? - 是否可以使用语法
std::make_unique<Foo>({ &b })
我想要哪个?
完整示例如下:
#include <initializer_list>
#include <memory>
struct Bar
{};
struct Foo
{
Foo(std::initializer_list<Bar*> bars)
{ }
};
int main()
{
Bar b;
// initializer_list able to be deduced from { &b }
Foo f ({ &b });
// initializer_list not able to be deduced from { &b }
std::unique_ptr<Foo> p = std::make_unique<Foo>({ &b });
(void)f;
return 0;
}
最佳答案
make_unique
使用完美转发。
完美转发不完美有以下几个方面:
转发初始化列表失败
它将
NULL
或0
转换为一个整数,然后不能将其传递给指针类型的值。它不知道它的参数是什么类型,所以你不能做需要知道它们类型的操作。例如:
struct Foo { int x; }; void some_funcion( Foo, Foo ) {}; template<class...Args> decltype(auto) forwarding( Args&& ... args ) { return some_function(std::forward<Args>(args)...); }
调用
some_function( {1}, {2} )
是合法的。它使用{1}
和{2}
构造Foo
。调用
forwarding( {1}, {2} )
不是。它在您调用forwarding
时不知道参数将是Foo
,因此它无法构造它,也无法通过代码(因为构造列表不是变量或表达式)。如果您传递一个重载的函数名称,则无法在调用点计算出哪个重载。并且一组重载不是一个值,所以你不能完美转发它。
您不能传递位域。
它强制引用它的参数,即使转发的目标没有。这会以可能导致程序在技术上格式错误的方式“使用”一些静态常量数据。
无法转发对未知大小数组
T(&)[]
的引用。但是,您可以调用带有T*
的函数。
其中大约一半来自 this comp.std.c++ thread ,一旦我记得还有其他问题我想不起来了,我就开始寻找它。
关于c++ - std::initializer_list 无法从 <brace-enclosed initializer list> 推导出来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35230920/