Std::initializer_list和引用类型

std::initializer_list and reference types

本文关键字:引用类型 list initializer Std      更新时间:2023-10-16

std::initializer_list可以包含引用类型(右值和左值)吗?还是必须使用指针或引用包装器(如std::ref)?

编辑:

可能需要更多的说明:

我有一个成员变量::std::vector<std::function<void()> >,我想将一个lambda对象转发到其中。这通常是用emplace_back完成的,但是我想在构造函数的初始化列表中完成。唉,当我阅读时,这将使转发不可能。

std::initializer_list可以包含引用类型(右值和左值)吗?

std::initializer_list<T>不包含对其元素的引用。它使用复制语义,将其值保存为const对象:

18.9 初始化列表 [support.initlist]

类型为initializer_list<E>的对象提供了对类型为const E的对象数组的访问。

引用的initializer_list将导致编译错误,因为内部指针用于迭代器:

#include <initializer_list>
int main()
{
    int x;
    std::initializer_list<int&> l = {x};
    // In instantiation of 'class std::initializer_list<int&>':
    // error: forming pointer to reference type 'int&'
    // typedef const _E*  iterator;
}

initializer_list也不支持移动语义,因为const对象不能被移动。如果您希望保持引用语义,那么将对象保存在std::reference_wrapper<T>中是最可行的解决方案。

From http://www.cplusplus.com/reference/initializer_list/initializer_list/

initializer_list对象被自动构造为一个数组类型T的元素

因此它们不能与std::initializer_list<int&>之类的东西一起使用。原因与下面给出编译错误的原因相同

int& arr[20];

错误:将' arr '声明为引用数组

,这是c++标准规定的:https://stackoverflow.com/a/1164306/1938163

这里不需要初始化列表

正如其他人提到的,您不能将std::initializer_list用于引用。您可以使用std::initializer_list<std::reference_wrapper<...>>,但它将阻止您将右值作为参数传递给构造函数,因为std::reference_wrapper只能绑定左值。换句话说,以下代码将无法编译:

YourContainerOfFunctions C{ [](){} };

这使得在您的情况下使用std::initializer_list既不高效也不方便。

使用可变模板代替!

我相信这就是你想要达到的目标:

class Foo {
  std::vector<std::function<void()>> Functions;
public:
  template <class... FuncTs>
  Foo(FuncTs &&...Funcs) : Functions({std::forward<FuncTs>(Funcs)...}) {}
};
void foo(){};
int main() {
  auto boo = []() {};
  std::function<void()> moo = []() {};
  Foo F{
      foo, boo,      // passed by reference, then copied
      []() {},       // moved, then copied
      std::move(moo) // moved, then also moved
  };
}

这要求每个参数最多复制一次,这是必要的,因为std::function总是复制构造它的functor对象。一个例外是从相同类型的std::function构造std::function