【问题标题】:Having a constexpr static string gives a linker error拥有 constexpr 静态字符串会导致链接器错误
【发布时间】:2016-04-19 22:41:03
【问题描述】:

以下程序给了我一个链接时错误:

#include <iostream>

struct Test { static constexpr char text[] = "Text"; };

int main()
{
    std::cout << Test::text << std::endl; // error: undefined reference to `Test::text'
}

错误信息是

/tmp/main-35f287.o: In function `main':
main.cpp:(.text+0x4): undefined reference to `Test::text'
main.cpp:(.text+0x13): undefined reference to `Test::text'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

好的。让我们尝试解决这个问题:我在 struct 正文之外添加了一个定义:

#include <iostream>

struct Test { static constexpr char text[] = "Text"; };
constexpr char Test::text[] = "Text";

int main()
{
    std::cout << Test::text << std::endl;
}

Clang 给了我以下错误信息。

main.cpp:4:35: error: static data member 'text' already has an initializer
    constexpr char Test::text[] = "Text";
                                  ^
main.cpp:3:50: note: previous initialization is here
    struct Test { static constexpr char text[] = "Text"; };

哦,好吧,我想,现在我知道你想要什么了:

#include <iostream>

struct Test { static constexpr char text[]; };
constexpr char Test::text[] = "Text";

int main()
{
    std::cout << Test::text << std::endl;
}

又是一个错误:

main.cpp:3:41: error: declaration of constexpr static data member 'text' requires an initializer
    struct Test { static constexpr char text[]; };

狗咬自己的尾巴。 :(

有没有办法使用在类中声明的编译时常量字符数组?我想要一个类中的数据的原因是我需要一个类型特征类来帮助我做模板的东西。

【问题讨论】:

  • 你的意思是简单的struct Test { static const char text[] = "Text"; };
  • 您已经尝试了两个选项 - 类外部的初始化器,内部和外部。现在,还有第三种选择……
  • 这很好用:struct Test { static constexpr auto text = "Text"; };
  • @vincentp 不错。这是最简洁的写法。避免重复。值得被接受的答案。
  • @vincentp 跟进你的评论,我问了这个问题stackoverflow.com/questions/34793392/…

标签: c++ string c++11 constexpr typetraits


【解决方案1】:

应该工作:

#include <iostream>

struct Test { static constexpr char text[] = "Text"; };
constexpr char Test::text[];

int main()
{
    std::cout << Test::text << std::endl;
}

在标准 (n4140 §9.4.2/3) 中,您可以找到:

可以在类中声明一个字面量类型的静态数据成员 使用 constexpr 说明符定义;如果是,其声明应 指定一个大括号或相等初始化器,其中每个初始化器子句 也就是说,赋值表达式是一个常量表达式。 [注:在 在这两种情况下,成员都可能出现在常量表达式中。 -结尾 note ] 该成员仍应在命名空间范围内定义,如果它是 程序中使用的 odr-used (3.2) 和命名空间范围定义应 不包含初始化程序

【讨论】:

  • 只有一个初始化初始化赋值。
  • 为我工作!谢谢!
【解决方案2】:

正如 cmets 所说,这个版本运行良好:

struct Test { static constexpr auto text = "Text"; };

但是text 将是const char* 而不是char[]

【讨论】:

  • 为什么不能使用const char[5] 呢?我的意思是为什么会有这么大的差异?这很烦人。这使得它无法用于我的目的。
猜你喜欢
  • 2018-11-06
  • 2012-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多