类静态 constexpr 的 C++ 链接器错误
我正在用 g++-4.6.1 --std=c++0x
编译以下简单程序:
I am compiling the following simple program with g++-4.6.1 --std=c++0x
:
#include <algorithm>
struct S
{
static constexpr int X = 10;
};
int main()
{
return std::min(S::X, 0);
};
我收到以下链接器错误:
I get the following linker error:
/tmp/ccBj7UBt.o: In function `main':
scratch.cpp:(.text+0x17): undefined reference to `S::X'
collect2: ld returned 1 exit status
我意识到内联定义的静态成员没有定义符号,但我的(可能有缺陷的)印象是使用 constexpr
告诉编译器始终将符号视为表达式;因此,编译器会知道传递对符号 S::X
的引用是不合法的(出于同样的原因,您不能引用文字 10代码>).
I realize that inline-defined static members do not have symbols defined, but I was under the (probably flawed) impression that using constexpr
told the compiler to always treat the symbol as an expression; so, the compiler would know that it is not legal to pass a reference to the symbol S::X
(for the same reason you can't take a reference to the literal 10
).
但是,如果 S 被声明为命名空间,即命名空间 S"而不是结构 S",则一切都可以正常链接.
However if S is declared as namespace, i.e. "namespace S" instead of "struct S", everything links fine.
这是一个 g++
错误还是我仍然需要使用技巧来解决这个烦恼?
Is this a g++
bug or do I still have to use a trick to workaround this annoyance?
推荐答案
我不认为这是一个错误.如果将 constexpr
更改为 const
,它仍然会失败,并出现完全相同的错误.
I don't think this is a bug. If you change the constexpr
to const
, it still fails, with the exact same error.
您已经声明了 S::X
,但没有在任何地方定义它,因此没有存储空间.如果你对它做任何需要知道它的地址的事情,那么你也需要在某个地方定义它.
You've declared S::X
, but not defined it anywhere, so there's no storage for it. If you do anything with it that needs to know the address of it then you'll need to define it somewhere also.
例子:
int main() {
int i = S::X; // fine
foo<S::X>(); // fine
const int *p = &S::X; // needs definition
return std::min(S::X, 0); // needs it also
}
这样做的原因是 constexpr
可以在编译时进行评估,但不是要求这样评估,并且可以同样发生在运行时.它没有指示编译器始终将符号视为表达式",它暗示如果编译器愿意,这样做是明智和允许的.
The reason for this is that constexpr
can be evaluated at compile time, but it's not required to be evaluated as such, and can equally happen at runtime. It doesn't instruct "the compiler to always treat the symbol as an expression", it hints that it would be sensible and permissible to do so if the compiler felt like it.
相关文章