编译时循环优化

问题描述 投票:4回答:1

我发现有点难以理解为什么以下结果会导致编译时计算。我已经阅读了thisthisthis以及关于stackoverflow的更多问题,告诉我下面的代码(至少对我的理解)不应该在编译时因为while循环而计算(代码只是一个例子来说明题):

template< unsigned N >
constexpr unsigned isStringNice(const char (&arr)[N], unsigned pos = 0)
{
    //we do not like the 'D' char :)
    int currPos = 0;
    while(currPos < N){
        if(arr [currPos] == 'D'){
            throw 1;
        }
        currPos ++;
    }
    return 1;
}
constexpr unsigned isIdxValid( unsigned idx, unsigned len){
    return idx >= len?  throw 1 : idx;
}

template< unsigned N >
constexpr char nth_char(const char (&arr)[N], unsigned pos){
  return  isStringNice(arr),isIdxValid(pos, N),arr[pos];
}

int main(){

  constexpr char b = nth_char("ABC", 2);

  return b;
}

这个输出没有标志以下assembly代码(gcc 8.2,谢谢Godbolt)主要:

push    rbp
mov     rbp, rsp
mov     BYTE PTR [rbp-1], 67
mov     eax, 67
pop     rbp
ret

和-O3

main:
        mov     eax, 67
        ret

请注意,那里没有跳转,while条件没有分支,没有。我的印象是for-loops和while循环were not possible在编译时进行评估。但是,编译器(gcc 8.2)在编译时评估结果。我唯一想到的是这是因为循环展开,所以我尝试使用-fno-unroll-loops,但这导致相同的汇编代码。另一方面从我的经验来看,这个标志更像是编译器建议而不是保证而gcc可能仍然会展开即使设置了标志,循环也是如此。

我的问题的简短版本:如何在编译时评估constexpr函数中的while循环?

c++ c++11 gcc c++17 constexpr
1个回答
9
投票

在C ++ 14中,放松了constexpr函数的要求。

以前,在C ++ 11中,constexpr函数只能包含typedefs,static_asserts和usings,但只能包含一个return语句。

在C ++ 14中,可以在constexpr函数体中使用循环。

因为b被声明为constexpr char,所以必须在编译时进行评估。编译器然后优化了isStringNice函数,因为它在运行时没有使用。

© www.soinside.com 2019 - 2024. All rights reserved.