在这种情况下,为什么不是constexpr?

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

我有一个愚蠢的constexpr版本的strlen,编译器在某些情况下接受它作为constexpr,但在其他情况下它没有,这是一个例子:

template <std::size_t MAX_SIZE>
class FixedString
{
public:
    explicit FixedString(const char* str)
    {
        for(std::size_t i = 0; i < MAX_SIZE; i++)
        {
            data[i] = str[i];
        }
    }

    char data[MAX_SIZE];
};

constexpr std::size_t constexpr_strlen(const char *str)
{
    for(std::size_t i = 0; i < std::numeric_limits<std::size_t>::max(); i++)
    {
        if(str[i] == '\0')
        {
            return i;
        }
    }

    return 0;
}

// doesn't compile, compiler says non-type template argument is not a constant expression
auto make_string(const char* str)
{
    return FixedString<constexpr_strlen(str)>(str);
}

int main()
{
    constexpr bool IS_DEV = true;

    // works fine
    std::array<int, constexpr_strlen(IS_DEV ? "Development" : "Production")> arr;

    // works fine
    FixedString<constexpr_strlen(IS_DEV ? "Development" : "Production")> str("Develop");

    // doesn't compile, compiler says variable has incomplete type 'void'
    auto string = make_string("Not working");

    return 1;
}

为什么constexpr_strlen在make_string函数中被认为是constexpr而在它中不是?

对于我在这里看到的,它可以在编译时计算,不是吗?

c++ string compiler-errors constexpr
1个回答
3
投票

主要问题是constexpr函数的定义是在编译时和运行时都可调用。让我们从一个更简单的例子开始:

constexpr int f(int n) { return n };

int n = 7;

// n could be modified!

f(n); // compiler cannot know which value n has at runtime,
      // so the function needs to be executed at runtime as well!

f(7); // well, now right the opposite...

所以它很简单:constexpr函数的结果也是constexpr,当且仅当调用函数的所有参数都是constexpr本身时(并且只有这时,函数在编译时才被计算),否则,它将会是一个运行时值(并在运行时评估该函数)。

但是,在constexpr函数内部,编译器无法知道是否仅使用constexpr参数调用该函数;所以函数参数总是需要被认为是非constexpr。我们在这里......

(当然,make_string甚至不是constexpr,但如果constexpr不能用于constexpr函数的参数,那么对于正常的函数参数来说就更少了......)

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