我想在一些C++程序中使用PI常量和三角函数.我得到了三角函数include <math.h>.但是,此头文件中似乎没有PI的定义.
如何在不手动定义PI的情况下获取PI?
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
虽然 …
我想使用constexpr的标准版<cmath>一样的功能exp,log,pow在便携方式.我目前有一个非便携式解决方案g++将这些功能视为constexpr- 不兼容C++的扩展,但我担心可移植性和面向未来(我想这个扩展可能有一天会被删除g++).
我constexpr对这些函数的版本感兴趣,而不是模板元程序 - 我希望在编译时和运行时都可以使用相同的功能.我不需要C兼容性,但我确实需要快速实现 - 诸如Taylor Series扩展之类的天真实现会太慢.
我该如何实现这些功能?我在特别感兴趣exp,log和pow
我从研究中学到了一些切向相关的东西
constexpr因为它们必须具有副作用(例如设置errno)以保持C兼容性constexpr,但作为C++ 14,这是禁止的(每个第一回答这个问题和回答这个问题).这是我担心函数可能不会出现constexpr在以后版本中的部分原因g++g++每个数学函数的实现foo只调用一个内置函数__builtin_foo,它被视为constexpr.我或许可以开始调用__builtin_foo函数而不是foo函数 - 即使相应的函数符合要求,这些函数仍可能保留constexpr在未来版本中- 但这只会有助于未来验证,而不是可移植性.g++foo请参阅更新以获得更好的问题示例.原始代码有各种各样的问题,使图片混乱:
这个问题为什么我可以在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)
所以它seems是gcc正在考虑的内置版本printf是一个常量表达式.gcc 这里构建的文档但不记录这种情况,其中非constexpr函数的内置可以被认为是常量表达式.
如果确实如此:
1.4 实现合规性第8段说(强调我的):符合条件的实现可能具有扩展(包括其他库函数),前提是它们不会改变任何格式良好的程序的行为.需要实现来诊断使用根据本国际标准格式不正确的扩展的程序.但是,这样做之后,他们就可以编译和执行这样的程序. …
有没有办法写一个类型特征来确定一个类型是否支持C++中的负零(包括整数表示,如符号和大小)?我没有看到任何直接这样做的东西,并且std::signbit似乎不是constexpr.
澄清:我问,因为我想知道这是否可能,无论用例是什么,如果有的话.
我正在尝试使用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) 不幸的是,两者都不能直接转换为初始化浮点数组; 我发现我在模板元编程方面不够合适,无法通过反复试验来解决这个问题.
首先让我声明一个用例:
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++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)
编译器似乎不喜欢constexpr但static const在这里的实际原因是什么?不constexpr应该在这里也有资格,或者这完全与这里的上下文有关并且constexpr不应该在函数之外声明?
谢谢你。