Can I Move Elements from std::initializer_list?
When using std::initializer_list, it's logical to believe that one can move elements out of it. However, the following code demonstrates otherwise:
#include <initializer_list> #include <utility> template<typename T> void foo(std::initializer_list<T> list) { for (auto it = list.begin(); it != list.end(); ++it) { bar(std::move(*it)); // Safe? } }
Contrary to expectations, attempting to move elements out of std::initializer_list results in copies instead. This arises due to the unique nature of std::intializer_list, which requires special compiler handling and lacks the value semantics of typical containers.
The issue lies with the return type of begin() and end() for std::initializer_list, which is const T . Therefore, the expression 'std::move(it)' produces an immutable rvalue reference (T const &&&), which cannot be effectively moved from. It merely binds to a function parameter of type T const & because rvalues bind to const lvalue references, resulting in copy semantics.
This behavior may seem counterintuitive, but it allows the compiler to potentially make the initializer_list a statically-initialized constant. Nonetheless, it introduces an inconsistency where the user is left uncertain about whether the result of begin() and end() is const or mutable.
The above is the detailed content of Can I Move Elements from a `std::initializer_list`?. For more information, please follow other related articles on the PHP Chinese website!