Reputation: 939
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
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