lundi 27 avril 2015

Constexpr compound assignment operator in clang and gcc

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:

  1. Which of the compilers is right (and why)?
  2. Is there a way to implement the operator|= such that g++ will accept it as a constexpr?

Aucun commentaire:

Enregistrer un commentaire