Violet Giraffe
Violet Giraffe

Reputation: 33579

For loop in constexpr function fails to compile with MSVC 19.23

The following code compiles in Clang and GCC, but fails in MSVC.

template <typename... FieldsSequence>
struct S {
    static constexpr bool checkIdUniqueness()
    {
        using IdType = int;
        constexpr IdType fieldIds[sizeof...(FieldsSequence)]{ 0 };
        for (size_t i = 0; i < std::size(fieldIds) - 1; ++i)
        {
            if (fieldIds[i] > fieldIds[i + 1])
            {
                constexpr auto tmp = fieldIds[i];
                fieldIds[i] = fieldIds[i + 1];
                fieldIds[i + 1] = tmp;
            }
        }

        return true;
    }
};

The error message is:

expression did not evaluate to a constant
note: failure was caused by a read of a variable outside its lifetime
note: see usage of 'i'

Is there a way to make this work with all the three compilers? Ultimately, I need to bubble-sort the array to assert at compile time that all the values are unique.

https://godbolt.org/z/9XbP6-

Upvotes: 1

Views: 400

Answers (1)

You overused constexpr declarations. For one, if fieldIds is declared constexpr then it's also const, and you can't mutate it. As for tmp, because it's declared constexpr the initializer must be a constant expression, but it can't be one really.

The correct approach is to remove constexpr from those declarations:

template <typename... FieldsSequence>
struct S {
    static constexpr bool checkIdUniqueness()
    {
        using IdType = int;
        IdType fieldIds[sizeof...(FieldsSequence)]{ 0 };
        for (size_t i = 0; i < std::size(fieldIds) - 1; ++i)
        {
            if (fieldIds[i] > fieldIds[i + 1])
            {
                auto tmp = fieldIds[i];
                fieldIds[i] = fieldIds[i + 1];
                fieldIds[i + 1] = tmp;
            }
        }

        return true;
    }
};

The function as a whole can still be evaluated in a constant expression, but there is no extra requirement on those variables now that can interfere with their declaration or usage.

Upvotes: 4

Related Questions