Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I forward-declare a constexpr object at namespace scope?

Tags:

c++

gcc

c++11

clang

On clang (trunk) I can forward declare an object that will later be defined with constexpr as follows:

// Fwd-declarations
struct S;
extern const S s;

// (... later) definitions
struct S {};
constexpr S s {};

Gcc 4.8 doesn't like this, telling me the forward-declaration and the definition differ in constexpr-ness. Is gcc speaking truth, or is this just a gcc bug?

like image 402
Eric Niebler Avatar asked Nov 13 '13 16:11

Eric Niebler


2 Answers

I can't find any language in my copy of the C++11 standard that explicitly forbids constexpr-ness from mis-matching between a declaration and a definition, but I do see language explicitly forbidding constexpr from being used with extern (section 7.1.5), and I also see language requiring the initializer for a class-level static constexpr variable to be in the class. Also, since the utility of constexpr is significantly reduced when the definition of the variable or its type is unavailable, I think it's likely the intent is that constexpr variables must be defined (or, for static class members, initialized) when they are declared.

As a work-around, perhaps you could provide an extern alias for the variable. This would allow you to take its address, and that's the only thing I can think of that a forward-declaration would allow. For example:

// .hpp file:
struct C;
extern C const &c;

// .cpp file:
struct C {
    constexpr C() { }
};
constexpr C cc;
C const &c = cc;

Side note: I know that in C++14, they revisited/are revisiting constexpr, so it's possible that it works in Clang because it's implementing some draft spec of C++14.

like image 77
Adam H. Peterson Avatar answered Sep 18 '22 19:09

Adam H. Peterson


The real answer is that gcc is plain wrong, clang is right. The code above should compile, and it will in gcc 4.9. Or so says this bug report.

like image 36
Eric Niebler Avatar answered Sep 19 '22 19:09

Eric Niebler