为什么非静态数据成员不能为constexpr? [英] Why can't non-static data members be constexpr?

查看:456
本文介绍了为什么非静态数据成员不能为constexpr?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是有效的代码:

struct S {
  constexpr S(int x, int y): xVal(x), yVal(y) {}
  constexpr S(int x): xVal(x) {}
  constexpr S() {}

  const int xVal { 0 };
  const int yVal { 0 };
};

但是在这里我真的想声明 xVal yVal constexpr -像这样:

But here I'd really like to declare xVal and yVal constexpr--like this:

struct S {
  constexpr S(int x, int y): xVal(x), yVal(y) {}
  constexpr S(int x): xVal(x) {}
  constexpr S() {}

  constexpr int xVal { 0 };         // error!
  constexpr int yVal { 0 };         // error!
};

如前所述,代码不会编译。原因是(按照7.1.5 / 1)只能将静态数据成员声明为 constexpr 。但是为什么

As indicated, the code won't compile. The reason is that (per 7.1.5/1), only static data members may be declared constexpr. But why?

推荐答案

考虑什么 constexpr 表示。这意味着我可以在编译时解析该值。

Think about what constexpr means. It means that I can resolve this value at compile time.

因此,类的成员变量本身不能为 constexpr ... xVal 所属的实例在实例化之前不存在!拥有 xVal 的东西可能是 constexp ,这将使 xVal 一个 constexpr ,但是 xVal 永远不可能是 constexpr

Thus, a member variable of a class cannot itself be a constexpr...the instance that xVal belongs to does not exist until instantiation time! The thing that owns xVal could be constexp, and that would make xVal a constexpr, but xVal could never be constexpr on its own.

这并不意味着这些值不能是const表达式……实际上,该类的constexpr实例可以将变量用作const表达式:

That does not mean that these values can't be const expression...in fact, a constexpr instance of the class can use the variables as const expressions:

struct S {
  constexpr S(int x, int y): xVal(x), yVal(y) {}
  constexpr S(int x): xVal(x) {}
  constexpr S() {}

  int xVal { 0 };
  int yVal { 0 };
};

constexpr S s;

template <int f>//requires a constexpr
int foo() {return f;}

int main()
{
   cout << "Hello World" << foo<s.xVal>( )<< endl; 

   return 0;
}

编辑:因此,下面进行了很多讨论,其中回顾了一个

So there has been alot of discussion below that reviewed that there was a couple of implied questions here.

采用以下示例:

//a.h
struct S;
struct A {std::unique_ptr<S> x; void Foo(); A();/*assume A() tries to instantiate an x*/}

//main.cpp

int main(int argc, char** argv) {
  A a;
  a->foo();
}


//S.h
struct S {
  constexpr S(int x, int y): xVal(x), yVal(y) {}
  constexpr S(int x): xVal(x) {}
  constexpr S() {}

  constexpr int xVal { 0 };         // error!
  constexpr int yVal { 0 };
};

A和S的定义可能在完全不同的编译单元中,因此S必须是直到链接时间才会知道constexpr,特别是如果A的实现被遗忘了。这种模棱两可的情况将很难调试和实现。更糟糕的是,S的接口可能会完全暴露在共享库,COM接口等中……这可能会完全更改共享库的所有基础结构,这可能是不可接受的。

The definition of A and S could be in completely different compilation units, so the fact that S must be constexpr may not be known until link time, especially if the implementation of A is forgotten. Such ambiguous cases would be hard to debug and hard to implement. Whats worse is that the interface for S could be exposed entirely in a shared library, COM interface, ect...This could entirely change all the infrastructures for a shared library and that would probably be unacceptable.

另一个原因是感染性。如果类中的任何成员均为constexpr,则所有成员(及其所有成员)和所有实例都必须为constexpr。请采用以下情形:

Another reason would be how infectious that is. If any of the members of a class were constexpr, all the members (and all their members) and all instances would have to be constexpr. Take the following scenario:

//S.h
struct S {
  constexpr S(int x, int y): xVal(x), yVal(y) {}
  constexpr S(int x): xVal(x) {}
  constexpr S() {}

  constexpr int xVal { 0 };         // error!
  int yVal { 0 };
};

任何S实例都必须是 constexpr 可以仅持有 constexpr xval yVal 本质上成为 constexpr ,因为 xVal 是。没有技术上的编译器原因,您不能这样做(我不认为),但感觉不太像C ++。

Any instance of S would have to be constexpr to be able to hold an exclusively constexpr xval. yVal inherently becomes constexpr because xVal is. There is no technical compiler reason you can't do that (i don't think) but it does not feel very C++-like.

可能只有标准委员会认为它没有是个好主意。就我个人而言,我发现它的实用性很小……我真的不想定义人们如何使用我的班级,而只是定义他们使用班级时我的班级表现。当他们使用它时,他们可以将特定实例声明为constexpr(如上所述)。如果我想在constexpr实例上放一些代码块,可以使用模板来完成:

Probably nothing other than the standards committee didn't think it was a good idea. Personally, I find it having very little utility...I don't really want to define how people use my class, just define how my class behaves when they use it. When they use it, they can declare specific instances as constexpr (as above). If I have some block of code that I would like a constexpr instance over, I'd do it with a template:

template <S s>
function int bar(){return s.xVal;}

int main()
{
   cout << "Hello World" << foo<bar<s>()>( )<< endl; 

   return 0;
}

尽管我认为使用constexpr函数可能会更好

Though I think you'd be better off with a constexpr function that could be used both in the restrictive an non restrictive ways?

constexpr int bar(S s) { return s.xVal; }

这篇关于为什么非静态数据成员不能为constexpr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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