std :: initializer_list无法从<brace-enclosed initializer =“”list =“”>

时间:2016-02-05 18:21:05

标签: c++ c++11

我有一个类,其构造函数采用initializer_list

Foo::Foo(std::initializer_list<Bar*> bars)

如果我尝试使用大括号括起初始化列表 直接创建对象,则会正确推断出initializer_list

Foo f ({ &b }); // std::initializer_list<Bar*> correctly deduced

但是,当尝试执行相同的间接(使用可变参数函数模板 - 在本例中为make_unique)时,编译器无法推导出initializer_list:< / p>

std::make_unique<Foo>({ &b }); // std::initializer_list<Bar*> not deduced

错误输出:

  

错误:没有匹配函数来调用‘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;
}

2 个答案:

答案 0 :(得分:4)

支撑的初始化程序没有类型。当您致电make_unique时,它会尝试推断出类型并失败。在这种情况下,您必须在调用时指定类型

std::make_unique<Foo>(std::initializer_list<Bar*>{ &b });

这将创建一个std::initializer_list<Bar*>,编译器可以推导出它,并将其转发到Foo::Foo(std::initializer_list<Bar*> bars)

Foo f ({ &b });工作的原因是编译器知道构造函数Foo(std::initializer_list<Bar*> bars),并且B*的支撑初始化列表可以隐式转换为std::initializer_list<Bar*>。没有类型扣除。

答案 1 :(得分:4)

make_unique使用完美转发。

完美转发在以下方面并不完美:

  • 无法转发初始化列表

  • 它将NULL0转换为整数,然后不能将其传递给指针类型的值。

  • 它不知道它的参数是什么类型,所以你不能做需要知道它们类型的操作。举个例子:

    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} )是合法的。它使用Foo{1}构建{2}

    呼叫forwarding( {1}, {2} )不是。它在您调用forwarding时不知道参数将是Foo,因此无法构造它,并且它无法通过代码传递构造初始化列表(作为构造列表)不是变量或表达式。)

  • 如果传递重载的函数名称,则无法在调用点处计算出哪个重载。并且一组重载不是一个值,所以你不能完美地推进它。

  • 您无法通过位域。

  • 它强制引用其参数,即使转发的目标没有。这&#34;使用&#34;一些静态const数据可能会导致程序在技术上形成错误。

  • 无法转发对未知大小T(&)[]的数组的引用。但是,您可以使用T*来调用函数。

其中大约一半是从this comp.std.c++ thread中提取的,我记得有一次,我记得还有其他一些我无法回想起的问题。