c++ - 在头文件中使用 `const char thing[] = "foo";`?

标签 c++ dry one-definition-rule

我想创建一个常量全局字符数组,这样

  • 它可以在多个翻译单元中使用。
  • 数组的长度是从用于初始化它的字符串文字推导出来的。
  • 该字符串文字在我的源代码中只存在一次(如果可能的话还有目标文件)。
  • 其中所有翻译单元都可以在编译时访问长度。
  • 当多个翻译单元链接在一起时没有 ODR 违规。

理论上,这应该可以通过使用 const char[] 并将减速/定义以一种强制将数据/符号放入 COMDAT 部分的方式放入头文件中,但我不这样做不知道标准(甚至任何编译器)是否支持它。

附注假设使用的任何习语都将用于许多文件中的成百上千个常量。


编辑:我所知道的给出所有要点的“最干净”的解决方案是:

template<bool> struct data_ {
  static const char kFoo[];
};

template<> const char data_<true>::kFoo[] = "bar\0other\0stuff\0";
typedef data_<true> data;


#include <stdio.h>

template<typename T, int N>
void Print(T(&var)[N]) { printf("%d %s\n", N, var); }

int main() { Print(data::kFoo); return 0; }

还是比较丑。


OTOH 如果我只是扔掉 3b(保证相同的存储模块内联)那么这个工作:

const char kFoo[] = "bar\0other\0stuff\0";

因为它默认有内部链接。一个好的链接器可以合并这些,但那时你不能说任何关于地址/标识符相等性之间的关系(即不要将它转换为指针并将其用作标识)。但这是一个警告,几乎一直都是良性的。

最佳答案

标题:

#define LITERAL "Hello, world"
extern char const literal[sizeof LITERAL];

一个源文件:

char const literal[] = LITERAL;

仍然不能保证任何特定的编译器/链接器只复制一个字符串文字(但它确实保证 &literal[0] 在所有单元中都相同的要求)。

关于c++ - 在头文件中使用 `const char thing[] = "foo";`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25980238/

相关文章:

c++ - 为什么将 set::iterator 而不是 const_iterator 传递给函数会违反单一定义规则?

c++ - 为什么在内联函数内部调用的函数不需要定义?

c++ - 使用带重音的单词会出错

python - 如何从PyObject str获取char字符串?

ruby-on-rails - 我应该将 "global"共享部分模板放在哪个文件夹中?

ios - 如何在 iOS/Objective C 中 DRY 代码?

c++ - 如何正确添加状态栏?

c++ - 设置项目根?

ios - 我怎样才能在一个额外的功能中外包这种重复的代码味道? iOS Swift 函数

c++ - 为什么将内联函数def放在其他包含内联函数声明的头文件的头文件中是链接错误?