如果有一个constexpr if语句,为什么不是其他constexpr语句呢?

时间:2017-08-16 05:16:42

标签: c++ c++17

是否有任何理由只将if constexpr包含在C ++ 17中?

我可以这样做:

template <int N>
constexpr int fib() {
    if constexpr (N == 1 || N == 2) {
        return 1;
    } else {
        return fib<N - 1>() + fib<N - 2>();
    }
}

为什么C ++委员会也没有考虑switch constexpr

template <int N>
constexpr int fib() {
    switch constexpr (N) {
        case 1:
        case 2: return 1;
        default: return fib<N - 1>() + fib<N - 2>();
    }
}

switch constexpr

显得更酷

甚至是一个过早的编译时循环与for constexpr / while constexpr展开而不使用模板替换/递归模板函数:

constexpr void printFoo() {
    for constexpr (auto i = 0; i < 10; i++) {
        cout << fib<i>() << endl;
    }
}

它们是否会包含在C ++ 20 /未来版本的C ++中?

3 个答案:

答案 0 :(得分:28)

if constexpr被提议相对接近于最终确定的C ++ 17。

装饰(如switch)可能推迟了它的包含。

像强制循环展开这样的花哨肯定会有。

改变C ++标准需要真正的工作。你必须自己在编译器中实现它作为证明它可以完成,说服其他编译器编写者应该很容易或值得努力,弄清楚它应该在标准中措辞明确和明确,说服其他成员委员会认为你的改变不只是语言等等。

不需要出现的原因。事情不会一直发生。 C ++改进不是某种自然过程,除非有人阻止它,

Tl;博士:因为你没有提出建议并通过标准化来实现它。立即开始,可能是在C ++ 20中。 “我不值得”提出建议不是一个借口:这是工作需要做的事情,而不是一些非常棒的恩惠。通过做这项工作,一个人变得很棒。 “我很懒”是一个借口,一个我非常熟悉的借口。

答案 1 :(得分:13)

C ++标准委员会通常不会因为“看起来很酷”而添加新功能。每个新功能仅在提交论文后添加,该论文提出精确制定的法律术语,精确指定功能的语法和语义,通常会经过多次修订,因为专家会对所有含义进行清理。

这为添加新功能提供了一个天然的障碍:如果它添加到语言中的功能不足以使这种艰苦的体验变得有价值,那么没有人愿意正式提出它。

if constexpr是该语言的一个有价值的补充(尝试重写代码不使用它,你会明白为什么)并且指定并不复杂:如果条件为真,那么第二个子语句是丢弃,否则第一个子语句被丢弃。

相比之下,由于switch constexpr陈述更复杂,switch会在措辞方面造成更大的困难。 (不过,欢迎您尝试。)例如,您对这应该如何运作有一个自然的期望:

switch constexpr (x) {
  case 1:
    bar<x>();
    if constexpr(y) { break; }
  case 2:
    baz<x>();
}

即如果x为1且y为真,则baz<x>未实例化,但如果x为1且y为false,则{ {1}} 实例化。如果你想要这些语义,你需要弄清楚标准,它必须指定一个有效的程序来确定要丢弃哪些语句(请记住,这些baz<x>if可以是任意嵌套)。如果您不想要这些语义,那么switch可能不会比一堆switch constexpr更强大,但与普通if constexpr语句相比会有限制。

switch进一步加剧了这些困难。现在,它可能是值得的。但有人必须付出努力。

答案 2 :(得分:0)

不是答案,但评论时间太长。您可以使用#pragma unroll在英特尔(R)编译器中展开编译时循环。

void bar();

constexpr void foo() {
    #pragma unroll(10)
    for (auto i = 0; i < 10; i++) {
        bar();
    }
}

void baz()
{
    foo();
}
关于Godbolt的

Live example 证明展开。