繁体   English   中英

std :: initializer_list无法从中推断出来<brace-enclosed initializer list>

[英]std::initializer_list not able to be deduced from <brace-enclosed initializer list>

我有一个类,其构造函数采用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

错误输出:

错误:没有用于调用'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它会尝试推断出类型并失败。 在这种情况下,您必须在调用时指定类型

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* s的支撑初始化列表可以隐式转换为std::initializer_list<Bar*> 没有类型扣除。

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

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

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

  • 你无法通过位域传递。

  • 它强制引用其参数,即使转发的目标没有。 这“使用”某些静态const数据的方式会导致程序在技术上形成错误。

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

其中大约一半是从这个comp.std.c ++线程中获取的 ,我记得有一次,我记得有其他问题我无法回想起来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM