C++ 如果有';这是一个constexpr if语句,为什么其他constexpr语句不能呢?
如果C++17中只包含constexpr,有什么理由吗 我可以这样做:C++ 如果有';这是一个constexpr if语句,为什么其他constexpr语句不能呢?,c++,c++17,C++,C++17,如果C++17中只包含constexpr,有什么理由吗 我可以这样做: template <int N> constexpr int fib() { if constexpr (N == 1 || N == 2) { return 1; } else { return fib<N - 1>() + fib<N - 2>(); } } 使用开关constexpr 甚至在不使用模板替换/递归模板函数的情况下
template <int N>
constexpr int fib() {
if constexpr (N == 1 || N == 2) {
return 1;
} else {
return fib<N - 1>() + fib<N - 2>();
}
}
使用开关constexpr
甚至在不使用模板替换/递归模板函数的情况下,使用for constexpr
/而使用constexpr
展开过早的编译时循环:
constexpr void printFoo() {
for constexpr (auto i = 0; i < 10; i++) {
cout << fib<i>() << endl;
}
}
constexpr void printFoo(){
对于constexpr(自动i=0;i<10;i++){
CC++标准委员会一般不会因为“看起来很酷”而添加新的特性。。每个新功能只有在提交了一篇论文后才会添加,该论文提出了精心编制的法律术语,精确地指定了功能的语法和语义。由于专家们对所有含义进行了详细分析,这些术语通常会经过多次修订
这为添加新特性提供了一个自然的障碍:如果它将添加到语言中的功能不足以使这种繁重的体验变得有价值,那么没有人会正式提出它
如果constexpr
是该语言的一个有价值的补充(请尝试重写代码,不要使用它,您会看到原因),并且指定它并没有那么复杂:如果条件为true,则丢弃第二个子语句,否则丢弃第一个子语句
相比之下,switch-constexpr
在措辞上会造成更大的困难,因为switch
语句更为复杂。(不过,欢迎您尝试一下。)例如,您自然会对其工作方式有一个期望:
switch constexpr (x) {
case 1:
bar<x>();
if constexpr(y) { break; }
case 2:
baz<x>();
}
开关constexpr(x){
案例1:
bar();
如果constexpr(y){break;}
案例2:
baz();
}
也就是说,如果x
为1且y
为真,则不会实例化baz
,但如果x
为1且y
为假,则会实例化baz
。如果需要这些语义,则需要找出标准ESE,它必须指定一个有效的过程来准确地确定哪种类型要丢弃的h语句(请记住,这些if
s和switch
es可以任意嵌套)。如果您不想要这些语义,您的switch constexpr
可能不会比一堆If constexpr
更强大,但与正常的switch
语句相比会有一些限制
这些困难随着constexpr的而进一步增加。现在,这可能是值得的。但必须有人付出努力。如果constexpr
是在接近C++17定稿时提出的
修饰(比如开关
)可能推迟了它的加入
像“强制循环展开”这样的花哨游戏肯定会有
需要改变C++标准的实际工作。你必须在编译器中实现它,证明它是可以完成的,说服其他编译器编写者应该是容易的或值得的努力,去弄清楚它应该如何在标准中措辞清楚和明确,让委员会的其他成员相信你的改变不是简单的。关于语言等
<>不需要理由“强”>“不”/“强”发生。事情不会一直发生。C++改进不是一些自然过程,除非有人停止它,
Tl;dr:因为你没有提出,也没有通过标准化来实现。从今天开始,它可能是在C++20中提出的。“我不值得”提出并不是借口:这是需要做的工作,不是令人敬畏的恩赐。一个人通过做工作变得很棒。“我很懒”这是一个我非常熟悉的借口。不是答案,但评论太长。您可以使用#pragma unroll
在英特尔(R)编译器中展开编译时循环
void bar();
constexpr void foo() {
#pragma unroll(10)
for (auto i = 0; i < 10; i++) {
bar();
}
}
void baz()
{
foo();
}
void bar();
constexpr void foo(){
#布拉格展开(10)
用于(自动i=0;i<10;i++){
bar();
}
}
void baz()
{
foo();
}
然后写一个建议。“看起来酷多了”这不是一个很好的理由。我相信我们只得到了if constexpr
,因为如果我们试图同时包含整个批次的话,时间会更长;if constexpr
的优点和缺点比for constexpr
或switch constexpr
更容易衡量。“switch constexpr看起来酷多了”。准备好成为一名巨魔吧。如果你愿意花宝贵的时间研究并写出一份好的提案,你就足够有声望了。我投票结束这个问题,因为“为什么X不是语言功能?”?"对于任何人来说,这都不是一个可以令人满意的问题。这不是一个必须在编译器中实现的正式要求。没有太多的正式要求,而且大部分都是程序性的。但这当然有助于说服WG21。在这种情况下,这是语法上的糖分。WG21主要关心的不是它是否可以被实现已修订,但语义是否定义良好且与语言的其他部分不冲突。@msalters是否constexor general loop展开真的只是糖?我的意思是,指定什么是可以的,什么是不可以的。索引变量的地址是否更改?或者看起来很疯狂。索引变量的地址到底是什么,insIDEAconstexpr
loop?禁止直接获取地址似乎是合乎逻辑的。这是完全可以解释/教导的:“编译器在编译时执行循环,因此没有运行时地址”@msalters所以我不能传递对该值的引用?即,没有ODR用法。或者应该实例化一个临时值吗?如果循环是for(int x=0;test(x);inc(x))
?一篇初始论文可能会建立从switch constepr
到一个等效但更详细的
void bar();
constexpr void foo() {
#pragma unroll(10)
for (auto i = 0; i < 10; i++) {
bar();
}
}
void baz()
{
foo();
}