JensB
JensB

Reputation: 939

Array constant not evaluating to constant even though only constexpr functions called in initialization

This is a simplified, reproducible version of my code:

type_id.h

template<typename>
void type_id() {}

typedef void(*type_id_t)();

c_sort.h (based on this answer)

template<typename Array>
constexpr void c_sort_impl(Array& array_) noexcept {
    using size_type = typename Array::size_type;
    size_type gap = array_.size();
    bool swapped = false;
    while ((gap > size_type{ 1 }) or swapped) {
        if (gap > size_type{ 1 }) {
            gap = static_cast<size_type> (gap / 1.247330950103979);
        }
        swapped = false;
        for (size_type i = size_type{ 0 }; gap + i < static_cast<size_type> (array_.size()); ++i) {
            if (array_[i] > array_[i + gap]) {
                auto swap = array_[i];
                array_[i] = array_[i + gap];
                array_[i + gap] = swap;
                swapped = true;
            }
        }
    }
}

template<typename Array>
constexpr Array c_sort(Array array_) noexcept {
    auto sorted = array_;
    c_sort_impl(sorted);
    return sorted;
}

foo.h

#include "type_id.h"
#include "c_sort.h"
#include <array>

template<class... Cs>
struct Foo
{
    constexpr static auto key =
        c_sort( std::array<type_id_t, sizeof...(Cs)>{ type_id<Cs>... } );
};

If I try to instantiate Foo, I get a compiler error telling me expression did not evaluate to a constant. Why is this? When initializing key, I only call functions marked with constexpr. What part of the expression can't be evaluated at compile-time?

Upvotes: 0

Views: 106

Answers (1)

Brian Bi
Brian Bi

Reputation: 119457

A recent version of GCC or Clang will tell you the evaluation that failed to yield a constant expression. See https://godbolt.org/z/adhafn8v7

The problem is the comparison:

array_[i] > array_[i + gap]

A comparison between unequal function pointers (other than to check whether or not they are equal) has an unspecified result, and therefore is not permitted inside a constant expression evaluation.

Upvotes: 3

Related Questions