标签: constexpr

为什么 constexpr 不是自动的?

据我所知, constexpr 可以被视为编译器的提示,以检查是否可以在编译时评估给定的表达式,并在可能的情况下进行评估。

我知道它也对声明为 constexpr 的函数或初始化施加了一些限制,但最终目标是编译时评估,不是吗?

所以我的问题是,为什么我们不能把它留给编译器呢?它显然能够检查前置条件,那么为什么它不对每个表达式进行检查并在可能的情况下在编译时进行评估呢?

关于为什么会这样,我有两个想法,但我还不确定它们是否达到了目的:

a) 在编译期间可能需要太长时间。

b) 由于我的代码可以在不允许 normale 函数的位置使用 constexpr 函数,因此说明符也是声明的一部分。如果编译器自己完成所有事情,则可以使用 C 数组定义中的函数和该函数的一个版本,但在下一版本中可能会出现编译器错误,因为编译时评估的前提条件是不比较满意。

c++ constexpr c++11

5
推荐指数
1
解决办法
645
查看次数

什么C++ 14规则禁止constexpr函数为数据成员分配?

我的理解是这个(荒谬的)代码无效C++ 14:

class Point  {
public:
  constexpr double setX(double newX) { return x = newX; }
private:
  double x;
};
Run Code Online (Sandbox Code Playgroud)

我想弄清楚C++ 14标准中的哪一部分(仍然正式起草)不允许它.对constexpr功能的限制在7.1.5/2中列出.(抱歉格式错误.我无法弄清楚如何击败降价使其看起来正确.)

constexpr函数的定义应满足以下约束:

  • 它不应是虚拟的(10.3);
  • 其返回类型应为字面类型;
  • 每个参数类型都应是文字类型;
  • 它的函数体应为= delete,= default或不包含的复合语句
    • asm-definition,
    • 一个goto声明,
    • 尝试块,或
    • 非文字类型或静态或线程存储持续时间的变量的定义,或者不执行初始化的定义.

那里没有任何禁止分配给数据成员的东西.在5.19/2(子弹15)中有这样的禁令(再次出现格式错误,抱歉):

条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:[...]对象的修改(5.17,5.2.6) ,5.3.2)除非它适用于文字类型的非易失性左值,指的是在e的评估范围内开始生命的非易失性对象;

但我不知道5.19如何适用于7.1.5.有人可以澄清一下吗?

c++ constexpr c++14

5
推荐指数
1
解决办法
1417
查看次数

使用constexpr或struct进行元编程

我们刚开始在C++ 11中学习模板元编程.作为练习,我们编写了一个程序,输出int值的二进制表示.我们想出了两个可能的实现.第一个使用带有枚举值的递归,而第二个方法使用constexpr函数.

我们的期望是两个实现都会产生相同大小的可执行文件.但是,第一个实现导致9064字节,而第二个实现9096字节.我们不介意字节上的微小差异,但不明白导致差异的原因.

我们使用GCC 4.8.2编译了没有优化标志的程序,但是,找到了相同的结果-O2标志.

#include <iostream>
using namespace std;

template <int val>
struct Bin
{
    enum { value = 10 * Bin<(val >> 1)>::value + (val & 1) };
};

template <>
struct Bin<0>
{
    enum { value = 0 };
};

constexpr int bin(int val)
{
  return val == 0 ? 0 : (10 * bin(val >> 1) + (val & 1));
}


int main()
{
  // Option 1
  cout << Bin<5>::value  << '\n'
       << Bin<27>::value << '\n'; …
Run Code Online (Sandbox Code Playgroud)

c++ template-meta-programming constexpr c++11

5
推荐指数
1
解决办法
529
查看次数

Constexpr找到实现

在回答完这个问题并阅读本文后,看看这段代码,我想constexpr find用简单的数组类实现.

考虑以下示例:

#include <cstddef>

template <class It, class T>
constexpr auto constexpr_find(const It& b, const It& e, T value) {
    auto begin = b;
    while (begin != e) {
        if (*begin == value) break;

        ++begin;
    }
    return *begin;
}

template<typename T, size_t N>
class array
{
public:
   typedef T* iterator;
   typedef const T* const_iterator;
   constexpr auto begin() const { return const_iterator(array_); }
   constexpr auto end() const { return const_iterator(array_ + N); …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++14

5
推荐指数
1
解决办法
1237
查看次数

如何在编译时初始化浮点数组?

我已经发现了两个好方法在编译时间初始化积分阵列这里这里.

不幸的是,两者都不能直接转换为初始化浮点数组; 我发现我在模板元编程方面不够合适,无法通过反复试验来解决这个问题.

首先让我声明一个用例:

constexpr unsigned int SineLength  = 360u;
constexpr unsigned int ArrayLength = SineLength+(SineLength/4u);
constexpr double PI = 3.1415926535;

float array[ArrayLength];

void fillArray(unsigned int length)
{
  for(unsigned int i = 0u; i < length; ++i)
    array[i] = sin(double(i)*PI/180.*360./double(SineLength));
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,至于信息的可用性推移,这种阵列可以被宣布constexpr.

但是,对于链接的第一种方法,生成器函数f必须如下所示:

constexpr float f(unsigned int i)
{
  return sin(double(i)*PI/180.*360./double(SineLength));
}
Run Code Online (Sandbox Code Playgroud)

这意味着float需要类型的模板参数.这是不允许的.

现在,我想到的第一个想法是将float存储在一个int变量中 - 计算后数组索引没有任何反应,所以假装它们是另一种类型(只要字节长度相等) )完全没问题.

但请看:

constexpr int f(unsigned int i)
{
  float output = sin(double(i)*PI/180.*360./double(SineLength)); …
Run Code Online (Sandbox Code Playgroud)

c++ arrays templates constexpr c++14

5
推荐指数
1
解决办法
1695
查看次数

在头文件中前向声明 constexpr 函数

假设我有以下文件。这是无效的 C++(链接器阻塞,所以是的)还是我的语法错误?constexpr 函数的前向声明是否必须与其定义在同一个文件中?

头文件.h

extern constexpr int fun(int);
Run Code Online (Sandbox Code Playgroud)

源文件

constexpr int fun(int x) 
{
    return x * 2; 
}
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++11 c++14

5
推荐指数
1
解决办法
2959
查看次数

为什么 constexpr 数据成员不是隐式静态的?

如果你这样做:

constexpr int LEN = 100;
Run Code Online (Sandbox Code Playgroud)

LEN变量定义为const无需键入const关键字。
它还具有static存储功能,无需键入static关键字。

另一方面,如果我们在class

struct A{
   constexpr static int SIZE = 100;
};
Run Code Online (Sandbox Code Playgroud)

SIZE仍然定义为const不需要输入 const 关键字,

然而SIZE不是static数据成员。
您需要static明确键入。如果不这样做,将出现编译错误。

问题是:
需要显式输入的原因是什么static

language-lawyer constexpr c++11

5
推荐指数
1
解决办法
909
查看次数

constexpr - 函数不能用于常量表达式

我想在编译时为给定范围内的数学函数计算查找表,然后在运行时从表中检索值.我的代码如下:

#include <iostream>
#include <cmath>


template<int size>
class LookupTable {
public:
constexpr LookupTable(double xMin, double xMax) : array(), xMin(xMin), xMax(xMax), dx((xMax - xMin) / (size - 1)) {
    for(auto i = 0; i < size; ++i)
        array[i] = exp(xMin + i * dx);
}

constexpr double operator()(double x) const {
    return array[std::min(std::max(static_cast<int>((x - xMin) / dx), 0), size-1)];
}

private:
double array[size];
double xMin;
double xMax;
double dx;
};



int main() {
    const double x = 0.5;
    constexpr LookupTable<10000> table(0.0, …
Run Code Online (Sandbox Code Playgroud)

c++ g++ cmath constexpr c++14

5
推荐指数
1
解决办法
3162
查看次数

为什么在增加 -fconstexpr-steps 后无法解析常量表达式?

以下面的 constexpr 为例:

#include <iostream>

constexpr int fib(const int i)
{
  if (i == 0) return 0;
  if (i == 1) return 1;
  return fib(i-1) + fib(i-2);
}

int main(){
  std::cout << fib(45) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

尽管是 constexpr,但它不会在编译时进行评估。
我学到的强制编译时评估的技巧如下:

#include <iostream>
#include <type_traits>

#define COMPILATION_EVAL(e) (std::integral_constant<decltype(e), e>::value)

constexpr int fib(const int i)
{
  if (i == 0) return 0;
  if (i == 1) return 1;
  return fib(i-1) + fib(i-2);
}

int main(){
  std::cout << COMPILATION_EVAL(fib(45)) << '\n';
} …
Run Code Online (Sandbox Code Playgroud)

c++ compile-time-constant constexpr clang++ c++17

5
推荐指数
1
解决办法
893
查看次数

定义constexpr静态数据成员

因此,我知道在C ++中,如果静态成员是const文字类型,则可以在类内部对其进行初始化,如下所示:

class test{
public:
        static constexpr int stc = 1;
private:
        int a = 0;
        int b = 0;
        int c = 0;
};
Run Code Online (Sandbox Code Playgroud)

静态constexpr变量stc可以用在编译器可以直接替换成员值的地方,即

int main () {int array[test::stc];}  
Run Code Online (Sandbox Code Playgroud)

但是,如果在不能由编译器直接替换值的上下文中使用:

int main() { const int &cs = test::stc; } 
Run Code Online (Sandbox Code Playgroud)

然后编译器(c)生成一个错误

c++ -std=c++11 -pedantic    t.cpp   -o t
Undefined symbols for architecture x86_64:
  "test::stc", referenced from:
      _main in t-a8ee2a.o
ld: symbol(s) not found for architecture x86_64
Run Code Online (Sandbox Code Playgroud)

除非静态成员是在类外部定义的,例如:

constexpr int test::stc;

为什么会这样呢?

c++ static class constexpr c++11

5
推荐指数
1
解决办法
1050
查看次数