constexpr函数与extern静态表

时间:2016-11-20 15:40:26

标签: c++ c++11 constexpr one-definition-rule

有类似的问题,但我没有发现直接回答这个问题。

我想实现这样的constexpr函数:

constexpr int Foo(int x) {
  static const int table[128] = { 3, 1, 4, 1, 5, ..., 99 };
  return (0 <= x && x < 128) ? table[x] : 42;
}

我担心如图所示使表函数静态,因为编译器可能会添加昂贵的检查以使表线程的初始化安全(减慢每个调用),并且这些检查可能使优化器不太可能内联这个琐碎的功能。

因此我认为我将表移动到名称空间静态,在一个.cpp文件中定义它,而函数本身仍然在标题中定义,以便它可以内联。

constexpr int Foo(int x) {
  extern constexpr int table[];
  return (0 <= x && x < 128) ? table[x] : 42;
}

编译器抱怨我无法在constexpr函数中声明table。所以我试过了:

extern constexpr int table[];
constexpr int Foo(int x) {
  return (0 <= x && x < 128) ? table[x] : 42;
}

这是不允许的,因为你不能只声明constexpr,你必须定义它。但是如果我在头文件中定义表,我会违反单定义规则,对吗?

constexpr int table[128] = { 3, 1, 4, 1, 5, ..., 99 };
constexpr int Foo(int x) {
  return (0 <= x && x < 128) ? table[x] : 42;
}

我知道Foo没有违反ODR,因为constexpr意味着内联函数定义。编译器接受了这个并且似乎做了正确的事情,但我知道编译器不需要为ODR违规发出诊断。

Q1:在最后一次迭代中,table是ODR违规吗?

Q2:如果没有,是否有办法阻止table对包含此标题的每个翻译单元可见?

1 个答案:

答案 0 :(得分:0)

不确定Q1(如果您定义table static?)但是,对于Q2,我建议将Foo()作为friend函数用于{{1}的类}}是table private成员。

以示例

static constexpr