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?
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).
Although the standard doesn't explicitly mention whether the definition of a constexpr
static member function is allowed to be separate from its declaration, it has the following example of a separate definition of a constexpr
constructor, under 7.1.5p1:
struct pixel {
int x;
int y;
constexpr pixel(int); // OK: declaration
};
constexpr pixel::pixel(int a)
: x(square(a)), y(square(a)) // OK: definition
{ }
So it seems clear that constexpr
functions can have separate declaration and definition. Also in 7.1.5p1:
If any declaration of a function or function template has
constexpr
specifier, then all its declarations shall contain theconstexpr
specifier.
This implies that a constexpr
function can have (multiple) non-definition declarations.
I'm pretty sure that g++ is correct. In fact this used to be a bug in g++. I can't find a place in the standard that explicitly says that you can have a static constexpr declaration separate from the definition, but if you look in section 7.1.5 that talks about the constexpr specifier ( summarized here ), it doesn't rule it out, which generally means that it is allowed.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.