constexpr的静态元组类成员有链接器错误

Mar*_*ork 5 c++ constexpr c++11

我有以下代码:

#include <iostream>
#include <tuple>

class T
{
    public:
        using Names = std::tuple<char const*, char const*>;
        static constexpr Names names {"First", "Second"};
};

int main()
{
    std::cout << std::get<0>(T::names);
}
Run Code Online (Sandbox Code Playgroud)

由于namesconstexpr我期待这个工作.但我收到一个链接器错误:

编译器:

> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud)

错误:

> g++ -std=c++1y pl.cpp
Undefined symbols for architecture x86_64:
  "T::names", referenced from:
      _main in pl-377031.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

[现场演示]

Col*_*mbo 7

static类中数据成员的声明永远不是定义1.
每当变量使用odr时都需要定义2. 每个引用std::get<>接受参数,并将变量绑定到引用odr-立即使用它3.

简单定义names外部:

constexpr T::Names T::names; // Edit: This goes *outside* the class "as is"!
Run Code Online (Sandbox Code Playgroud)

演示.


1) [basic.def]/2:

声明是一个定义,除非[..]声明static类定义中的数据成员(9.2,9.4)

2) [basic.def.odr]/4:

每个程序应该只包含该程序中使用的每个非内联函数或变量的一个定义; 无需诊断.

3)根据[basic.def.odr]/3:

除非应用左值到右值转换(4.1)以产生不调用任何非平凡函数的常量表达式(5.19),否则x其名称显示为可能已评估的表达式 的变量将被ex使用.如果是object,是表达式的潜在结果集合的元素,其中左值到右值的转换(4.1)应用于或者是丢弃值表达式(第5节).exxxexeee

这里的id-expression T::names指的是有问题的变量.唯一superexpression e包含的所有可能的结果T::namesT::names自己,因为设置的函数调用的潜在结果,即std::get<0>(T::names),是空的.但是,显然没有应用左值到右值的转换,并且T::names显然也没有丢弃值(因为它被传递给函数).
因此它使用起来并且需要定义.