相关疑难解决方法(0)

如何在C++中使用PI常量

我想在一些C++程序中使用PI常量和三角函数.我得到了三角函数include <math.h>.但是,此头文件中似乎没有PI的定义.

如何在不手动定义PI的情况下获取PI?

c++ trigonometry

437
推荐指数
16
解决办法
98万
查看次数

它是一个符合标准的编译器扩展,将非constexpr标准库函数视为constexpr吗?

gcc 在没有警告的情况下编译以下代码:

#include <cmath>

struct foo {
  static constexpr double a = std::cos(3.);
  static constexpr double c = std::exp(3.);
  static constexpr double d = std::log(3.);
  static constexpr double e1 = std::asin(1.);
  static constexpr double h = std::sqrt(.1);
  static constexpr double p = std::pow(1.3,-0.75);
};

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

的上面使用的标准库函数都不是constexpr功能,我们允许使用它们,其中一个常量表达式从两个需要草案C++ 11标准草案C++ 14标准7.1.5 [dcl.constexpr] :

[...]如果它是由构造函数调用初始化的,那么该调用应该是一个常量表达式(5.19).否则,或者如果在引用声明中使用constexpr说明符,则其初始值设定项中出现的每个完整表达式都应为常量表达式.[...]

即使使用-std=c++14 -pedantic-std=c++11 -pedantic没有生成警告(请参见实时).使用-fno-builtin产生错误(参见实时),表明这些标准库函数的内置版本被视为constexpr

虽然 …

c++ gcc language-lawyer c++11 c++14

38
推荐指数
1
解决办法
2952
查看次数

constexpr exp,log,pow

我想使用constexpr的标准版<cmath>一样的功能exp,log,pow在便携方式.我目前有一个非便携式解决方案g++将这些功能视为constexpr- 不兼容C++的扩展,但我担心可移植性和面向未来(我想这个扩展可能有一天会被删除g++).

constexpr对这些函数的版本感兴趣,而不是模板元程序 - 我希望在编译时和运行时都可以使用相同的功能.我不需要C兼容性,但我确实需要快速实现 - 诸如Taylor Series扩展之类的天真实现会太慢.

我该如何实现这些功能?我在特别感兴趣exp,logpow

我从研究中学到了一些切向相关的东西

  • 这些功能的标准兼容版本在技术上并不是constexpr因为它们必须具有副作用(例如设置errno)以保持C兼容性
  • 在C++ 11,一种实现被允许进行这些功能constexpr,但作为C++ 14,这是禁止的(每个第一回答这个问题回答这个问题).这是我担心函数可能不会出现constexpr在以后版本中的部分原因g++
  • g++每个数学函数的实现foo只调用一个内置函数__builtin_foo,它被视为constexpr.我或许可以开始调用__builtin_foo函数而不是foo函数 - 即使相应的函数符合要求,这些函数仍可能保留constexpr在未来版本中- 但这只会有助于未来验证,而不是可移植性.g++foo

c++ language-lawyer constexpr c++11

18
推荐指数
2
解决办法
3374
查看次数

gcc是否将非常量表达式函数的内置函数视为常量表达式

请参阅更新以获得更好的问题示例.原始代码有各种各样的问题,使图片混乱:

这个问题为什么我可以在constexpr函数中调用非constexpr函数?提出了以下代码

#include <stdio.h>

constexpr int f()
{
    return printf("a side effect!\n");
}

int main()
{
    char a[f()];
    printf("%zd\n", sizeof a);
}
Run Code Online (Sandbox Code Playgroud)

我回答的是格式不正确gcc 4.8.2允许它(现场观看).

但是,如果我们使用该-fno-builtin标志gcc生成错误(请参见它):

error: call to non-constexpr function 'int printf(const char*, ...)'
     return printf("a side effect!\n");
                                     ^
Run Code Online (Sandbox Code Playgroud)

所以它seemsgcc正在考虑的内置版本printf是一个常量表达式.gcc 这里构建的文档但不记录这种情况,其中非constexpr函数的内置可以被认为是常量表达式.

如果确实如此:

  • 是否允许编译器执行此操作?
  • 如果他们被允许,他们不必记录它是否符合要求?
  • 这可以被视为一个扩展,如果是这样的话,似乎需要一个警告,因为C++草案标准部分1.4 实现合规性8段说(强调我的):

符合条件的实现可能具有扩展(包括其他库函数),前提是它们不会改变任何格式良好的程序的行为.需要实现来诊断使用根据本国际标准格式不正确的扩展的程序.但是,这样做之后,他们就可以编译和执行这样的程序. …

c++ gcc language-lawyer constant-expression c++11

11
推荐指数
2
解决办法
1445
查看次数

是否有可能在编译时测试类型是否支持C++中的负零?

有没有办法写一个类型特征来确定一个类型是否支持C++中的负零(包括整数表示,如符号和大小)?我没有看到任何直接这样做的东西,并且std::signbit似乎不是constexpr.

澄清:我问,因为我想知道这是否可能,无论用例是什么,如果有的话.

c++ signed types type-traits negative-zero

8
推荐指数
1
解决办法
253
查看次数

如何使用少于8 GB的ram编译带有模板的余弦表?

我正在尝试使用2.14签名格式(2位有符号整数,14位分数)生成固定点算术的余弦/正弦表.余弦/正弦的参数被归一化并折叠在180度,90度和45度轴附近,因此我只需要从0到45度(或12867作为定点)的余弦值和正弦值.代码计算一个稍大的表,从0到1弧度(或16384作为固定点).

我已经为8.8,7.9,6.10,5.11,4.12和3.13位固定点测试了这段代码但是无法为2.14位定点编译它.当g ++使用大约7 GiB的ram并且仍在增长时,我停止了它.

那么如何让模板使用更少的ram?

#include <stdint.h>
#include <math.h>

template <uint16_t...> struct IndexList {};

template <uint16_t left_base, typename LeftList,
          uint16_t right_base, typename RightList> struct Merge;

template <uint16_t left_base, uint16_t... left,
          uint16_t right_base, uint16_t... right>
struct Merge<left_base, IndexList<left...>,
             right_base, IndexList<right...> > {
    typedef IndexList<left..., right...> Result;
};

template <uint16_t base, uint16_t n> struct Indexes {
    static constexpr uint16_t left_base = base;
    static constexpr uint16_t left = n / 2;
    static constexpr uint16_t right_base = base + n / 2;
    static constexpr …
Run Code Online (Sandbox Code Playgroud)

c++ templates variadic-templates

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

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

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

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

首先让我声明一个用例:

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 double

我目前正在研究更多 C++11 的东西,并在constexpr. 在我的一本书中,据说您应该将它用于常量,例如 ? 例如以这种方式:

#include <cmath>

// (...)

constexpr double PI = atan(1) * 4;
Run Code Online (Sandbox Code Playgroud)

现在我想把它放在一个自己的命名空间中,例如。MathC

// config.h

#include <cmath>

namespace MathC {
    constexpr double PI = atan(1) * 4;
    // further declarations here
}
Run Code Online (Sandbox Code Playgroud)

...但这里 IntelliSense 说function call must have a constant value in a constant expression

当我声明PI以下方式时,它有效:

static const double PI = atan(1) * 4;
Run Code Online (Sandbox Code Playgroud)

编译器似乎不喜欢constexprstatic const在这里的实际原因是什么?不constexpr应该在这里也有资格,或者这完全与这里的上下文有关并且constexpr不应该在函数之外声明?

谢谢你。

c++ constexpr c++11

2
推荐指数
1
解决办法
644
查看次数