I have the following code:
main.cpp
#include <cstdint>
#include <type_traits>
enum class FooEnum : uint8_t{
Foo1 = 0,
Foo2 = 1
};
constexpr uint32_t& operator|= (uint32_t& lhs, FooEnum rhs) {
return lhs |= 1u << static_cast<uint8_t>(rhs);
}
int main() {
uint32_t bar{0};
bar|=FooEnum::Foo1;
}
So essentially, the |=
operator is supposed to take an enum and set the bit, whose position corresponds to its integral value.
When compiled with clang++ 3.5.0 on fedora 21, everything works fine, but when compiled with g++ 4.9.2, it throws an error saying that this is not a constant-expression:
main.cpp: In function ‘constexpr uint32_t& operator|=(uint32_t&, FooEnum)’:
main.cpp:16:2: error: expression ‘(lhs = (lhs | (1u << ((int)rhs))))’ is not a constant-expression
}
^
This is true for all kinds of compiler flag combinations, but you can e.g. test it with g++ -std=c++11 -o a.out main.cpp
(c++14 doesn't make a difference)
So my questions are:
- Which of the compilers is right (and why)?
- Is there a way to implement the
operator|=
such that g++ will accept it as aconstexpr
?
EDIT:
In case you are wondering, why I tried to declare the operator as constexpr
in the first place although this isn't required in the example:
In my actual code, I'm using the |=
-operator in order to implement the (constexpr) |
-operator, which I wanted to be usable in a constexpr expression, but before that, I stumbled over the difference between the two compilers, not realizing, that gcc4.9 doesn't fully support c++14 (yet accepting the -std=c++14
flag).
When using the operator to actually initialize a global constexpr variable, even clang only compiles it with c++14 flag.
operator|=
inherently non-const? – Barry-std=c++14
. – MikeMB