I have a discrepancy between the behaviour of g++ 4.8.1 and clang++ 3.4.
I've got a class A
, of literal type, that has an explicit
constexpr
conversion function to type enum class E
.
Gcc allows me to initialize constexpr
variables of type E
from a constant expression of type A
using the conversion function in some cases, but not when the variable is a static class member (e2
below)
Clang rejects the initialization in all contexts (e1
, e2
and e3
).
According to [over.match.conv]p1
use of an explicit conversion function is OK here
enum class E { e };
struct A { explicit constexpr operator const E() const noexcept { return E::e; } };
constexpr E e1{A{}}; // Gcc: OK, Clang: Error
struct B { static constexpr E e2{A{}}; }; // Gcc: Error, Clang: Error
void f() { static constexpr E e3{A{}}; } // Gcc: OK, Clang: Error
I see a similar pattern when converting to another literal class type instead of an enum type - g++ rejects the initialization of s1
, clang rejects the initialization of s1
, s2
and s3
. I think these should be valid as well, as per [over.match.copy]p1
.
struct S { constexpr S(){} constexpr S(const S&){}};
struct A { explicit constexpr operator S() const noexcept { return S(); } };
constexpr S s1{A{}}; // Gcc: OK, Clang: Error
struct B { static constexpr S s2{A{}}; }; // Gcc: Error, Clang: Error
void f() { static constexpr S s3{A{}}; } // Gcc: OK, Clang: Error
Which compiler, if either, is right?
Edit: A couple of interesting things to note:
e2
/s2
and e1
/e3
/s1
/s3
, see http://coliru.stacked-crooked.com/a/daca396a63425c6b. gcc and clang-svn agree, but I'm not convinced that rejecting e2 and s2 is correct.Strangely enough, Clang appears to be correct in rejecting these.
The reason is that there is a bug in the C++11 standard in which {}
doesn't work for copy constructors. This is why ()
constructors work, but {}
constructors don't.
Bjarne Stroustrup says under the errata for his book that it's fixed in C++14
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With