std::initializer_list可以包含引用类型(右值和左值)吗?或者必须使用指针或引用 Package 器(例如std::ref)吗?编辑:也许应该进一步澄清:我有一个成员变量::std::vector<std::function<void()> >,我想把一个lambda对象转发到它里面,这通常是用emplace_back来完成的,但是我想在构造函数的初始化列表中完成,唉,正如我读到的,这会使转发变得不可能。
std::initializer_list
std::ref
::std::vector<std::function<void()> >
emplace_back
jaxagkaj1#
std::initializer_list可以包含引用类型(右值和左值)吗?std::initializer_list<T>不保存对其元素的引用。它通过将其值保存为const对象来使用 copy-semantics:18.9初始化程序列表[support.initlist]initializer_list<E>类型的对象提供对const E类型的对象数组的访问。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也不支持move-semantics,因为const对象不能从std::reference_wrapper<T>中移出。如果你希望保持引用语义,将你的对象保存在std::reference_wrapper<T>中是最可行的解决方案。
std::reference_wrapper<T>
ffvjumwh2#
从http://www.cplusplus.com/reference/initializer_list/initializer_list/开始initializer_list对象是自动构造的,就像分配了类型T的元素数组一样因此,它们不能用于类似std::initializer_list<int&>的对象。原因与下面给出的编译器错误相同
std::initializer_list<int&>
int& arr[20];
错误:将"arr"声明为引用数组这是由C++标准规定的https://stackoverflow.com/a/1164306/1938163
w8f9ii693#
正如其他人提到的,你不能使用std::initializer_list和引用。你可以使用std::initializer_list<std::reference_wrapper<...>>,但是它会阻止你将右值作为参数传递给构造函数,因为std::reference_wrapper只能绑定到左值。换句话说,下面的代码将无法编译:
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总是复制构造它的函子对象。一个例外是从相同类型的std::function构造std::function
std::function
3条答案
按热度按时间jaxagkaj1#
std::initializer_list
可以包含引用类型(右值和左值)吗?std::initializer_list<T>
不保存对其元素的引用。它通过将其值保存为const
对象来使用 copy-semantics:18.9
初始化程序列表[support.initlist]
initializer_list<E>
类型的对象提供对const E
类型的对象数组的访问。initializer_list
的引用将导致编译错误,因为迭代器使用了内部指针:initializer_list
也不支持move-semantics,因为const
对象不能从std::reference_wrapper<T>
中移出。如果你希望保持引用语义,将你的对象保存在std::reference_wrapper<T>
中是最可行的解决方案。ffvjumwh2#
从http://www.cplusplus.com/reference/initializer_list/initializer_list/开始
initializer_list对象是自动构造的,就像分配了类型T的元素数组一样
因此,它们不能用于类似
std::initializer_list<int&>
的对象。原因与下面给出的编译器错误相同错误:将"arr"声明为引用数组
这是由C++标准规定的https://stackoverflow.com/a/1164306/1938163
w8f9ii693#
此处不需要列表初始化
正如其他人提到的,你不能使用
std::initializer_list
和引用。你可以使用std::initializer_list<std::reference_wrapper<...>>
,但是它会阻止你将右值作为参数传递给构造函数,因为std::reference_wrapper
只能绑定到左值。换句话说,下面的代码将无法编译:这使得在您的情况下使用
std::initializer_list
既不高效也不方便。请改用可变参数模板!
我相信这就是你想要达到的目标:
每个参数最多需要一个副本,这是必要的,因为
std::function
总是复制构造它的函子对象。一个例外是从相同类型的std::function
构造std::function