其值可以被分配给一个`constexpr`参考?(Which values can be assig

2019-10-21 01:57发布

原来的问题

我想用静态成员变量,以便通过一个类型模板参数来传递信息到模板类。 这些变量不应包含在所有的翻译单位,这样我可以不用重新编译大部分的目标文件的更改他们的头文件中设置。 此外,这将是不错的,不需要额外的空间变量一个方便的别名。 我认为constexpr只读喜欢引用

static constexpr const int& alias = T::static_variable_name;

可以作为这样的别名,但不知道这是有效的。 对于一个限制constexpr

  • 构造函数的参数或值,以被分配必须只包含文字值,constexpr变量和函数。

所以,我想它使用g++ -std=c++11 ,并得到一种不一致的行为对我的口味。 该代码包含在这个问题的结束。 在大多数的情况下,代码编译并运行正常,但使用时h2g2_oracle::answer直接在非专业类模板(见注释“错误,为什么?”),编译失败与消息

 src/main.cpp:18:57: error: the value of 'h2g2_oracle::_answer' is not usable in a constant expression static constexpr const int& answer = h2g2_oracle::answer; // ERROR; WHY? src/main.cpp:11:9: note: 'int h2g2_oracle::_answer' is not const int h2g2_oracle::_answer = 42; 

为什么大多数的constexpr引用工作作为一个别名,这个单一的一个不?

#include <iostream>

// a specific kind of oracle
class h2g2_oracle {
  protected:
    static int _answer;

  public:
    static constexpr const int& answer = _answer; // public alias for reading
};
int h2g2_oracle::_answer = 42;

// some class template using a specific kind of oracle
template<typename oracle>
struct forecast {
  // try to define an own alias
  static constexpr const int& answer = oracle::answer; // works
  //static constexpr const int& answer = h2g2_oracle::answer; // ERROR; WHY?
};

// specialized version for the h2g2_oracle
template<>
struct forecast<h2g2_oracle> {
  // also define the own alias
  static constexpr const int& answer = h2g2_oracle::answer; // works
};

int main() {
  static constexpr const int& answer = h2g2_oracle::answer; // works
  std::cout << answer << std::endl;

  std::cout << forecast<h2g2_oracle>::answer << std::endl;
  return 0;
}

解决的意见

关于@Ben福格特的增益constexpr :是的,DYP 是正确的假设 ,我喜欢constexpr其体内初始化版本。 长注释:我很肯定,在一个单独的翻译单元初始化将迫使程序使用在原始值的地址存储一些内存的位置。 为此,我认为constexpr 总是在头文件,即静态成员的初始化,对模板(可能是有用的forecast<...>::answer )和非模板( h2g2_oracle::answer )。 我知道,我可以改变非模板类,包括一个虚拟的模板参数,这样可以初始化在头部进行为好,但仍与解决方案constexpr最初我感觉更轻松。

关于一个@dyp 可能的g ++的bug :啊,没想到找一个这样的“简单”的测试。 现在,我看到了相关的问题,这似乎是一个很好的解释给我。 任何可行的办法,我要确认/报告/帮助? 如果您对此非常有信心,我可以接受至少一个答案。

@dyp有关定义使用前 :是的,我检查了G ++是好的使用oracle::answer在非专业forecast即使定义h2g2_oracle自带的定义后forecast 。 然而, h2g2_oracle具有当是完整的 forecast<h2g2_oracle>::answer是在所使用的main 。 这看起来合理的我。 其他想法:我什么更着迷的是如何静态成员可以为其他静态成员(可能在不同的翻译单元)的引用进行初始化的方式。

@dyp关于

有趣的是,我不知道,如果你需要在H2G2预测使用前::回答的定义; 应该ODR使用的(我觉得奇怪)。

我觉得我得到了你的观点了。 这也是我觉得有趣的:事实上, int h2g2_oracle::_answer = 42; 甚至可以移动到不同的翻译单元,它仍然有效。 不知何故,链接器(IM简单的话)管理,以“插入”的正确的内存地址h2g2_oracle::_answer在需要的地方。

Answer 1:

简单的解决方法是内联,当然不需要存储:

template<typename oracle>
struct forecast
{
  static const int& answer() { return h2g2_oracle::answer; }
};

这也是C ++ 98兼容。



文章来源: Which values can be assigned to a `constexpr` reference?