Почему это не constexpr в этом случае? - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть тупая версия 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 считается constexprвне функции make_string и в ней нет?

Для того, что я вижу здесь, это может быть вычислено во время компиляции, не так ли?

1 Ответ

0 голосов
/ 22 февраля 2019

Основная проблема заключается в том, что функции 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 аргументами или нет;поэтому параметры функции всегда необходимо считать не-1022 *.И вот мы ...

(Конечно, make_string даже не constexpr, но если constexpr нельзя допустить для параметров функций constexpr, то еще меньше для параметров нормальной функции...)

...