从这个页面中可以看出,c ++ 11中的数学函数似乎都没有使用constexpr,而我相信所有这些函数都可以.所以这给我留下两个问题,一个是他们为什么选择不使函数constexpr.对于像sqrt我这样的函数来说,两个人可能会编写我自己的constexpr,但是像sin或cos这样的东西会比较棘手,所以它就在那里.
我正在研究核心常量表达式*中允许的内容,这在C++标准草案的5.19 常量表达式第2段中有所描述:
条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但是未评估的逻辑AND(5.14),逻辑OR(5.15)和条件(5.16)操作的子表达式不考虑[注意:重载的运算符调用函数.-end note]:
并列出随后的子弹中的排除项并包括(强调我的):
- 具有未定义行为的操作 [注意:包括,例如,有符号整数溢出(第5条),某些指针算术(5.7),除零(5.6)或某些移位操作(5.8) - 结束注释];
嗯?为什么常量表达式需要此子句来涵盖未定义的行为?常量表达式是否有一些特殊的东西需要未定义的行为才能在排除中进行特殊划分?
拥有这个条款是否给了我们没有它的任何优势或工具?
作为参考,这看起来像广义常量表达式提案的最新修订版.
使用此代码有什么好处
double x;
double square = pow(x,2);
Run Code Online (Sandbox Code Playgroud)
而不是这个?
double x;
double square = x*x;
Run Code Online (Sandbox Code Playgroud)
我更喜欢x*x并且查看我的实现(Microsoft)我发现pow没有优势,因为x*x比特定方形情况下的pow更简单.
有什么特别的情况,战俘优越吗?
在C++ 11中std::sqrt定义为constexpr,即它可以合法地从其他constexpr函数或编译时上下文中使用,如数组大小或模板参数吗?g ++似乎允许它(使用-std=c++0x),但我不确定我是否可以将其视为权威,因为c ++ 0x/c ++ 11支持仍然不完整.我似乎无法在互联网上找到任何东西的事实让我不确定.
看起来这应该是人们可以轻易找到使用谷歌的东西,但我已经尝试过(现在40分钟......)并且找不到任何东西.我可以找到几个建议,将constexpr添加到标准库的各个部分(例如这个),但没有关于sqrt或其他数学函数.
strcmp当我注意到这一点时,我正在玩,这里是代码:
#include <string.h>
#include <stdio.h>
int main(){
//passing strings directly
printf("%d\n", strcmp("ahmad", "fatema"));
//passing strings as pointers
char *a= "ahmad";
char *b= "fatema";
printf("%d\n",strcmp(a,b));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
-1
-5
Run Code Online (Sandbox Code Playgroud)
不应该strcmp一样吗?为什么,我给我传递一个字符串作为不同的值"ahmad"或作为char* a = "ahmad".将值传递给函数时,它们是否在其堆栈中分配?
N4527 5.20 [expr.const] p5
常量表达式是glvalue核心常量表达式,其值指的是一个实体,它是常量表达式的允许结果(如下定义),或者是一个prvalue核心常量表达式,其值是一个对象,对于该对象及其子对象:
- 引用类型的每个非静态数据成员是指一个实体,它是一个常量表达式的允许结果,和
- 如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象的结尾的地址(5.7),函数的地址或空指针值.
如果实体是具有静态存储持续时间的对象,则该实体是常量表达式的允许结果,该对象不是临时对象,或者是其值满足上述约束的临时对象,或者它是函数.
void foo(){
int a = 1;
int b[a || 1]{};//ok in gcc 5.1.0, error in clang 3.8.0
static_assert(a || 1,"");//ok in gcc 5.1.0, error in clang 3.8.0
switch(1){
case a || 1://ok in gcc 5.1.0, error in clang 3.8.0
;
}
}
Run Code Online (Sandbox Code Playgroud)
是a || 1一个不变的表达?
N4527 5.20 [expr.const] p2
条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:
(2.7) - 左值 - 右值转换(4.1),除非适用于
(2.7.1) - 整数或枚举类型的非易失性glvalue,它引用具有前面初始化的完整非易失性const对象,用常量表达式初始化,或者
(2.7.2) - 一个非易失性glvalue,引用字符串文字的子对象(2.13.5),或者
(2.7.3) - 一个非易失性glvalue,引用用constexpr定义的非易失性对象,或引用这种对象的不可变子对象,或者
(2.7.4) - …
鉴于源代码中唯一不同的两个程序是否存在constexpr,程序的含义是否可能发生变化?
换句话说,如果有一个编译器选项要求编译器尝试很难推断constexpr可能的地方,它会破坏现有的标准代码和/或以不好的方式改变其含义吗?
想象一下处理一个代码库,原始开发人员忘记将其包含constexpr在可能的地方,也许是在C++ 11之前编写的代码.如果编译器推断constexpr可以帮助您继续工作,那将会很棒.当然,或许它也应该在每次进行推理时发出警告,鼓励你明确添加constexpr后者.但它仍然有用.我担心它会破坏东西吗?
到目前为止,我唯一能想到的是constexpr函数是隐含的,inline并且可能存在添加inline可能以不良方式改变事物的情况; 例如,如果您违反了单定义规则.
我想使用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请考虑以下代码:
#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)
我本来期望编译器抱怨printf内部的调用f,因为f应该是constexpr,但printf不是.为什么程序编译和打印15?
根据C++标准,C++标准库的实现是否允许加强标准noexcept定义的方法和C++标准库的其他功能?
例如,如果C++标准指定了一些函数,std::f那么void f();允许实现它的标准库实现void f() noexcept;呢?