哪些值可以分配给`constexpr`引用? [英] Which values can be assigned to a `constexpr` reference?

查看:252
本文介绍了哪些值可以分配给`constexpr`引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用静态成员变量,以便通过类型模板参数将信息传递到模板类中。这些变量不应在包含在所有转换单元中的头文件中设置,以便我可以在不重新编译大多数目标文件的情况下更改它们。此外,这将是很好的有一个方便的变量的别名,不需要额外的空间。我认为 constexpr 只读引用,如

I would like to use static member variables in order to pass information via a type template parameter into templated classes. These variables should not be set in a header file that is included in all translation units so that I can change them without recompiling most of the object files. Moreover, it would be nice to have a handy alias for the variable that does not require additional space. I thought that constexpr read-only references like

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

可以充当此类别,但不确定是否有效。 constexpr 的一个限制读取

could serve as such an alias, but was not sure if that is valid. One restriction for constexpr reads



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

所以我使用 g ++ -std = c ++ 11 并且我的品味有不一致的行为。代码包含在这个问题的结尾。在大多数情况下,代码编译和运行很好,但是当在非专门类模板中直接使用 h2g2_oracle :: answer 时(见注释ERROR; WHY? ),编译失败,并显示消息

So I tried it using g++ -std=c++11 and got kind of inconsistent behavior for my taste. The code is included at the end of this question. In most of the cases, the code compiles and runs fine, but when using h2g2_oracle::answer directly in the non-specialized class template (see comment "ERROR; WHY?"), compilation fails with the message


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 引用是否作为别名工作,这个单引号不会?

Why do most of the constexpr references work as an alias and this single one does not?

#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 Voigt有关 <$ c的收益$ c> constexpr :是的,dyp 是正确的假设,我喜欢 constexpr 版本在其内部的初始化。 长评论:我非常确定,单独的翻译单元中的初始化将强制程序使用存储原始值的地址的一些内存位置。因此,我认为 constexpr 可能有用的总是有标题中的静态成员初始化,即模板(预测< ...> :: answer )和非模板( h2g2_oracle :: answer )。我知道我可以更改非模板类包括一个虚拟模板参数,以便初始化也可以在头中完成,但仍然解决方案与 constexpr 最初感觉更容易。

Addressing the comments

@Ben Voigt concerning the gain of constexpr: Yes, dyp is right with the assumption that I like the constexpr version for its initialization inside the body. Long comment: I was very sure that an initialization in a separate translation unit would force the program to use some memory location where the address of the original value is stored. Therefor, I thought constexpr might be useful to always have the static member initialization in the header, i.e., for templates (forecast<...>::answer) and non-templates (h2g2_oracle::answer). I know that I could change the non-template class to include a dummy template parameter so that initialization could be done in the header as well, but still the solution with constexpr initially felt easier to me.

@dyp关于可能的g ++错误:啊,我没想到找到一个这样的简单测试。现在我看到相关的问题,这似乎是一个很好的解释。任何可行的方式,我确认/报告/帮助?如果你对此有足够的信心,我可以接受作为回答至少。

@dyp concerning a possible g++ bug: Ah, I did not expect to find one with such a "simple" test. Now that I see the related questions, that seems like a good explanation to me. Any practicable way for me to confirm/report/help? If you are quite confident with that, I could accept that as an answer at least.

@dyp涉及使用之前的定义:是的,我检查了g ++很好用使用 h2g2_oracle 的定义<> > 在 forecast 的定义之后。但是,当使用 forecast< h2g2_oracle> :: answer 时, h2g2_oracle 必须完成在 main 中。这看起来对我合理。 其他想法:我更加着迷的是如何将静态成员初始化为另一个静态成员(可能在不同的翻译单元)。

@dyp concerning definition before using: Yes, I checked that g++ is fine with using oracle::answer in the non-specialized forecast even if the definition of h2g2_oracle comes after the definition of forecast. However, h2g2_oracle has to be complete when forecast<h2g2_oracle>::answer is used in the main. This looks reasonable to me. Additional thought: What I am more fascinated about is the way how static members can be initialized as a reference to another static member (possibly in a different translation unit).

@dyp关于


有趣的是,我不知道你是否需要h2g2的定义: :在使用它之前回答预测;它应该是odr使用(我觉得奇怪)。

Interestingly, I'm not sure if you need a definition for h2g2::answer before using it in forecast; it should be odr-used (which I find strange).

我想我现在已经说明了。这也是我觉得迷人的:事实上, int h2g2_oracle :: _ answer = 42; 甚至可以移动到不同的翻译单位,它仍然可以工作。不知何故,链接器(im简单词)设法插入 h2g2_oracle :: _ answer 的正确的内存地址。

I think I got your point now. This is also what I find fascinating: In fact, the int h2g2_oracle::_answer = 42; can even be moved to a different translation unit and it still works. Somehow, the linker (im simple words) manages to "insert" the correct memory address of h2g2_oracle::_answer where it is needed.

推荐答案

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

Simple workaround which is inline and certainly requires no storage:

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

它也是C ++ 98兼容。

It is also C++98-compatible.

这篇关于哪些值可以分配给`constexpr`引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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