Search code examples
c++c++11rvalue-reference

static_cast with an explicit rvalue conversion operator


I am writing a simple wrapper class, and I want to provide explicit conversion operators to the wrapped type. The following code compiles fine with gcc

class wrap
{
    double value;
public:
    explicit wrap(double x) : value(x) {}
    explicit operator double&&() && { return std::move(value); }
};

int main() {
    wrap w(5);
    double && x (std::move(w) ); //ok
    double && y = static_cast<double&&>(std::move(w)); //clang reports an error here
}

But clang reports an error: cannot cast from lvalue of type 'typename std::remove_reference<wrap &>::type' (aka 'wrap') to rvalue reference type 'double &&'; types are not compatible.

As far as I know (see the latest draft, 5.2.9 §4) static_cast<T>(e) has the same semantic has T t(e), but clang does not refuse the latter.

Which compiler is right?


Solution

  • This is clang bug 19917. From the section of the standard you mentioned, §5.2.9/4:

    An expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t.

    In this case, T t(e); is well-formed and compiles on both compilers, so static_cast<T>(e) should too. GCC correctly accepts it.