c++ - std::initializer_list 无法从 <brace-enclosed initializer list> 推导出来

标签 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 :

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 使用完美转发。

完美转发不完美有以下几个方面:

  • 转发初始化列表失败

  • 它将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,因此它无法构造它,也无法通过代码(因为构造列表不是变量或表达式)。

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

  • 您不能传递位域。

  • 它强制引用它的参数,即使转发的目标没有。这会以可能导致程序在技术上格式错误的方式“使用”一些静态常量数据。

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

其中大约一半来自 this comp.std.c++ thread ,一旦我记得还有其他问题我想不起来了,我就开始寻找它。

关于c++ - std::initializer_list 无法从 <brace-enclosed initializer list> 推导出来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35230920/

相关文章:

c++ - 在 Mac 上使用 valgrind

c++ - QT Creator中如何使用FMOD工具?

c++ - 命名空间名称在范围内必须是唯一的。为什么?

c++ - 在 C++ 中对 std::atomic<bool> 使用比较和读/写操作?

c++ - 防止为给定类型实例化模板化成员函数

c++ - 在 Xcode 4.5 中, "Compiler Default"和 "C++ Standard Library"的 "C++ Language Dialect"是什么?

c++ - 为什么 C++ 标准库中没有 SIMD 功能?

c++ - 将数组动态分配到具有指针参数的函数中

c++ - 迭代器在C++内部如何工作?

c++ - 是否有任何理由不扩展 std::set 以添加下标运算符?