即使在初始化中仅调用 constexpr 函数,数组常量也不会评估为常量
Array constant not evaluating to constant even though only constexpr functions called in initialization
这是我的代码的简化、可重现版本:
type_id.h
template<typename>
void type_id() {}
typedef void(*type_id_t)();
c_sort.h(基于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>... } );
};
如果我尝试实例化 Foo
,我会收到编译器错误提示 expression did not evaluate to a constant
。为什么是这样?在初始化key
时,我只调用标有constexpr
的函数。表达式的哪一部分不能在编译时求值?
最新版本的 GCC 或 Clang 会告诉您未能生成常量表达式的计算。参见 https://godbolt.org/z/adhafn8v7
问题是比较:
array_[i] > array_[i + gap]
不相等的函数指针之间的比较(除了检查它们是否相等)有一个未指定的结果,因此不允许在常量表达式求值中。
这是我的代码的简化、可重现版本:
type_id.h
template<typename>
void type_id() {}
typedef void(*type_id_t)();
c_sort.h(基于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>... } );
};
如果我尝试实例化 Foo
,我会收到编译器错误提示 expression did not evaluate to a constant
。为什么是这样?在初始化key
时,我只调用标有constexpr
的函数。表达式的哪一部分不能在编译时求值?
最新版本的 GCC 或 Clang 会告诉您未能生成常量表达式的计算。参见 https://godbolt.org/z/adhafn8v7
问题是比较:
array_[i] > array_[i + gap]
不相等的函数指针之间的比较(除了检查它们是否相等)有一个未指定的结果,因此不允许在常量表达式求值中。