My current program is rejected by clang but compiles fine with gcc. It boils down to the following simplified example:
struct A {
static constexpr inline int one();
};
inline constexpr int A::one() { return 1; }
int main() {
return 0;
}
g++ 4.7.2 compiles it without errors (g++ -std=c++11 -Wall -g -o main example.cpp
). clang++ 3.1 rejects it:
$ clang++ -std=c++11 -Wall -g -o main example.cpp
example.cpp:6:25: error: conflicting types for 'one'
inline constexpr int A::one() { return 1; }
^
example.cpp:3:31: note: previous declaration is here
static constexpr inline int one();
^
1 error generated.
My bet is that gcc is right and and clang is wrong? The program should be legal C++11.
Interesting sidenote. If one
is implemented within the struct, clang no longer complains:
struct A {
static constexpr inline int one() { return 1; }
}
gcc also accepts this variant. From my understanding, both versions should be identical according to the standard. Is it a clang bug or am I missing something?
A constexpr specifier used in a function or static data member (since C++17) declaration implies inline .
A constexpr function or constructor is implicitly inline .
Understanding constexpr Specifier in C++ constexpr is a feature added in C++ 11. The main idea is a performance improvement of programs by doing computations at compile time rather than run time. Note that once a program is compiled and finalized by the developer, it is run multiple times by users.
Yes. I believe putting such const ness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.
This was a Clang bug (fixed in Clang 3.2). The problem was that Clang wasn't correctly handling the impact of implicit const
ness when determining whether a redeclaration of a function matched a prior declaration. Consider:
struct A {
int f(); // #1
constexpr int f() const; // #2 (const is implicit in C++11 and can be omitted)
static constexpr int g(); // #3
};
int A::f() { return 1; } // #4, matches #1
constexpr int A::f() { return 1; } // #5, matches #2, implicitly const
constexpr int A::g() { return 1; } // #6, matches #3, not implicitly const
When matching the out-of-class declaration #5 against members of A
, the compiler has a problem: it doesn't know what type the new declaration of A::f
has yet. If A::f
is a non-static member function, then its type is int () const
, and if it's a static member function then its type is int ()
(no implicit const
).
Clang 3.1 didn't get this entirely right: it assumed that if a constexpr
function were a member function then the constexpr
made it implicitly const
, which allows #4 and #5 to work, but breaks #6. Clang 3.2 fixes this by implementing the constexpr
-implies-const
rule twice: once in redeclaration matching (such that #5 is considered to redeclare #2 and not #1, even though it isn't yet implicitly const
), and again once the prior declaration has been chosen (to add the implicit const to #5).
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