initializer_list and move semantics

No, that won't work as intended; you will still get copies. I'm pretty surprised by this, as I'd thought that initializer_list existed to keep an array of temporaries until they were move'd.

begin and end for initializer_list return const T *, so the result of move in your code is T const && — an immutable rvalue reference. Such an expression can't meaningfully be moved from. It will bind to an function parameter of type T const & because rvalues do bind to const lvalue references, and you will still see copy semantics.

Probably the reason for this is so the compiler can elect to make the initializer_list a statically-initialized constant, but it seems it would be cleaner to make its type initializer_list or const initializer_list at the compiler's discretion, so the user doesn't know whether to expect a const or mutable result from begin and end. But that's just my gut feeling, probably there's a good reason I'm wrong.

Update: I've written an ISO proposal for initializer_list support of move-only types. It's only a first draft, and it's not implemented anywhere yet, but you can see it for more analysis of the problem.


bar(std::move(*it));   // kosher?

Not in the way that you intend. You cannot move a const object. And std::initializer_list only provides const access to its elements. So the type of it is const T *.

Your attempt to call std::move(*it) will only result in an l-value. IE: a copy.

std::initializer_list references static memory. That's what the class is for. You cannot move from static memory, because movement implies changing it. You can only copy from it.