C++ 如何在命名空间作用域中正向声明constexpr对象?

C++ 如何在命名空间作用域中正向声明constexpr对象?,c++,gcc,c++11,clang,C++,Gcc,C++11,Clang,在clang(trunk)上,我可以向前声明一个对象,该对象将在以后使用constexpr定义,如下所示: // Fwd-declarations struct S; extern const S s; // (... later) definitions struct S {}; constexpr S s {}; GCC4.8不喜欢这样,告诉我转发声明和定义在constexpr-ness中有所不同。gcc说的是实话,还是这只是一个gcc错误?我在我的C++11标准副本中找不到任何语言明确

在clang(trunk)上,我可以向前声明一个对象,该对象将在以后使用
constexpr
定义,如下所示:

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

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

GCC4.8不喜欢这样,告诉我转发声明和定义在
constexpr
-ness中有所不同。gcc说的是实话,还是这只是一个gcc错误?

我在我的C++11标准副本中找不到任何语言明确禁止
constepr
-ness在声明和定义之间不匹配,但我确实看到语言明确禁止
constepr
extern
一起使用(第7.1.5节),我还看到,语言要求类级别的
static
constepr
变量的初始值设定项在类中。此外,由于变量或其类型的定义不可用时,
constepr
的效用会显著降低,我认为其目的可能是在声明变量时必须定义
constepr
变量(或者,对于
静态
类成员,初始化变量)

作为一种解决方法,也许您可以为变量提供
extern
别名。这将允许您记录其地址,这是我能想到的唯一一件事,转发声明将允许。例如:

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

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

旁注:我知道在C++14中,他们重访了/正在重访
constepr
,因此它可能在Clang中工作,因为它实现了C++14的一些规范草案。

真正的答案是gcc是完全错误的,Clang是正确的。上面的代码应该编译,并且将在GCC4.9中使用。或者这样说。

C++14草稿实现必须使用
-std=C++1y
启用;几乎没有一种方法是偶然做到的。@Griwes我现在不使用Clang(虽然我很想),所以我不知道,但这并不让我感到惊讶。但是,在使用C++14时,Clang可能已经全面(以兼容的方式)扩展了对
constexpr
的支持。我只是把它作为一种可能性扔掉。由于我在标准中找不到任何一种方式的赘言,这可能是因为这两种实现都是C++11的有效选择,或者这可能是一个标准缺陷。我已经归档了它。DyP,仅仅因为定义中必须使用
constexpr
,并不意味着不能向前声明对象,它只是意味着
constexpr
不能出现在向前声明中。到目前为止,我还没有看到任何东西告诉我我的原始代码是无效的。@AdamH.Peterson 3.1/2:“声明是一个定义,除非……它包含外部说明符(7.1.1)……并且既不是初始值设定项也不是函数体……”
constexpr
对象声明需要一个初始值设定项,
extern
只是不放弃该要求,而是
extern constexpr int q=3仍然有效。