简体   繁体   English

std::initializer_list 和引用类型

[英]std::initializer_list and reference types

Can a std::initializer_list contain reference types (both rvalue and lvalue)? std::initializer_list可以包含引用类型(右值和左值)吗? Or does one have to use pointers or a reference wrapper (such as std::ref )?还是必须使用指针或引用包装器(例如std::ref )?

EDIT:编辑:

Perhaps more clarification is due:也许需要更多说明:

I have a member variable, ::std::vector<std::function<void()> > , into which I would like to forward a lambda object.我有一个成员变量::std::vector<std::function<void()> > ,我想向其中转发一个 lambda 对象。 This would usually be accomplished with emplace_back , but I wanted to do it in the constructor's initialization list.这通常用emplace_back来完成,但我想在构造函数的初始化列表中完成。 Alas, as I read, this would make forwarding impossible. las,正如我所读,这将使转发变得不可能。

Can a std::initializer_list contain reference types (both rvalue and lvalue)? std::initializer_list包含引用类型(rvalue和lvalue)吗?

std::initializer_list<T> doesn't hold references to its elements. std::initializer_list<T>不包含对其元素的引用。 It uses copy-semantics by holding its values as const objects: 它通过将其值保存为const对象来使用复制语义

18.9 Initializer List [support.initlist] 18.9 初始化列表 [support.initlist]

An object of type initializer_list<E> provides access to an array of objects of type const E . initializer_list<E>类型的对象提供对const E类型的对象数组的访问。

An initializer_list of references will cause a compilation error because iternally pointers are used for iterators: 引用的initializer_list将导致编译错误,因为iternally指针用于迭代器:

#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;
}

An initializer_list also doesn't support move-semantics as const objects cannot be moved from. initializer_list也不支持move-semantics,因为const对象无法移动。 Holding your objects in a std::reference_wrapper<T> is the most viable solution if you wish to maintain reference-semantics. 如果您希望维护引用语义,那么将对象保存在std::reference_wrapper<T>是最可行的解决方案。

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

initializer_list objects are automatically constructed as if an array of elements of type T was allocated initializer_list对象自动构造,就像分配了类型为T的元素数组一样

thus they can't be used with something like std::initializer_list<int&> . 因此它们不能与std::initializer_list<int&>类的东西一起使用。 The reason is the same for which the following gives a compiler error 原因是相同的,以下给出了编译器错误

int& arr[20];

error: declaration of 'arr' as array of references 错误:将'arr'声明为引用数组

and that is dictated by the C++ standard: https://stackoverflow.com/a/1164306/1938163 这取决于C ++标准: https//stackoverflow.com/a/1164306/1938163

You do not need list initialization here您不需要在这里进行列表初始化

As others mentioned, you cannot use std::initializer_list with references.正如其他人提到的,您不能将std::initializer_list与引用一起使用。 You can use std::initializer_list<std::reference_wrapper<...>> , but it will prevent your from passing rvalues as arguments to the constructor, because std::reference_wrapper can only bind to lvalues.您可以使用std::initializer_list<std::reference_wrapper<...>> ,但它会阻止您将右值作为参数传递给构造函数,因为std::reference_wrapper只能绑定到左值。 In other words, the following will not compile:换句话说,以下不会编译:

YourContainerOfFunctions C{ [](){} };

This makes usage of std::initializer_list in your case neither efficient nor convenient.这使得在您的情况下使用std::initializer_list既不高效也不方便。

Use variadic templates instead!改用可变参数模板!

I believe that is what you wanted to achieve:我相信这就是您想实现的目标:

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
  };
}

This requires at most one copy per argument, necessary because std::function always make a copy of functor object which it is constructed from.每个参数最多需要一个副本,这是必要的,因为std::function总是复制构造它的仿函数对象。 An exception is construction of std::function from std::function of the same type一个例外是从相同类型的std::function ::function 构造std::function

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

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