静态元组类成员的constexpr具有链接器错误 [英] constexpr of static tuple class member has linker error

查看:57
本文介绍了静态元组类成员的constexpr具有链接器错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

#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);
}

由于名称为我希望 constexpr 可以工作。但是我得到一个链接器错误:

As names is a constexpr I expected this to work. But I get a linker error:

编译器:

> 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

错误:

> 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)

[实时演示]

推荐答案

在类中声明 static 数据成员绝不是定义 1

每当变量被odr-used 2 使用时,都需要一个定义。
std :: get<> 接受每个引用的参数,并将变量绑定到引用odr-立即使用它 3

A declaration of a static data member in class is never a definition1.
A definition is necessary whenever a variable is odr-used2. std::get<> takes arguments per reference, and binding a variable to a reference odr-uses it immediately3.

只需在外部定义名称

constexpr T::Names T::names; // Edit: This goes *outside* the class "as is"!

演示

1) [ basic.def] / 2:

1) [basic.def]/2:


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

A declaration is a definition unless [..] it declares a static data member in a class definition (9.2, 9.4)

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

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


每个程序都应仅包含每个非内联$ b $的一个定义b在该程序中使用的函数或变量;不需要诊断

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

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

3) According to [basic.def.odr]/3:


变量 x 的名称显示为可能值的表达式
ex ex 使用,除非应用左值到右值转换
( 4.1)到 x 会产生一个常量表达式(5.19),该表达式不会调用
任何非平凡函数,如果 x 是对象, ex
的元素,是表达式 e ,其中将
左值到右值转换(4.1)应用于 e e
的舍弃值表达式(第5条)。

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.19) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression (Clause 5).

此处的id表达式 T :: names 指的是有问题的变量。包含 T :: names 的所有可能结果的唯一超表达式 e T: :names 本身,因为函数调用的可能结果集,即 std :: get< 0>(T :: names),是空的。但是,显然不应用从左值到右值的转换,并且显然也不会丢弃 T :: names 的值(因为将其传递给函数)。

因此它很常用,需要定义。

Here the id-expression T::names refers to the variable in question. The only superexpression e that contains all the potential results of T::names is T::names itself, because the set of potential results of a function call, i.e. std::get<0>(T::names), is empty. However, the lvalue-to-rvalue conversion is clearly not applied, and the value of T::names is also clearly not discarded (as it is passed to a function).
Thus it is odr-used and requires a definition.

这篇关于静态元组类成员的constexpr具有链接器错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆