Question

I need to create a std::tuple<const XYZ,...> where XYZ is not copyable. Is something like that even possible? My current code

auto test() -> std::tuple<const XYZ> { return std::make_tuple(XYZ()); }

leads to C2248 in Visual Studio 2010... Which I find quite dubious as I'm constructing the tuple with an R-Value, so I'd assume that move-construction would kick in...

Était-ce utile?

La solution

Your problem is that the element is both noncopyable and const. The const XYZ element behaves as a const XYZ member; by 5.2.5p4 accessing the const XYZ element on an xvalue will yield an xvalue with union cv qualification i.e. having effective type const XYZ &&. That type is not suitable as an argument to the move constructor of XYZ so the deleted/private copy constructor will be attempted to be called instead.

Another way of looking at it is that a move constructor (e.g. the move constructor of std::tuple<...>) is obliged to ensure that its argument is left in an unspecified but valid state. By making the element const you've said that the only valid state for that element is the state it's constructed with, so the move constructor is not allowed to move from it, even if it is contained in an xvalue.

A workaround would be to define a const move constructor and const_cast its argument to delegate to the move constructor:

XYZ(const XYZ &&xyz): XYZ(const_cast<XYZ &&>(xyz)) {}

Amusingly, with gcc-4.7.2 it's enough to just declare the const move constructor; by RVO the actual call to the const move constructor can be elided. Don't rely on this.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top