如何在 c++11 中静态断言 std::array 类成员进行排序?



在编译时,如何断言std::array<uint8_t, 3>类成员已排序?这将允许它const,使用static_assert(),而不必在构造函数中调用std::sort()

在 c++20 中,std::is_sorted()已成为 constexpr,但不适用于以前的版本。

这是一个可以直接在std::array上调用的概念证明实现; 使其更通用(对于其他 constexpr 容器类型(留给读者作为练习:

template <typename T, std::size_t N>
constexpr bool is_sorted(std::array<T, N> const& arr, std::size_t from) {
return N - from == 0 or (arr[from - 1] <= arr[from] and is_sorted(arr, from + 1));
}
template <typename T, std::size_t N>
constexpr bool is_sorted(std::array<T, N> const& arr) {
return N == 0 or is_sorted(arr, 1);
}

免责声明:这需要 C++14,因为正如我在评论中提到的,您可能无法为 C++14 之前的std::array实现constexpr版本的is_sorted,因为对std::array的某些操作不是在 C++11 中constexpr1(operator[]/std::get<>(。

使用 C++14 实现,您可以在constexpr函数中使用标准for-loop 并使用以下非常简单的实现:

template<typename T, std::size_t N>
constexpr bool is_sorted(std::array<T, N> const &arr) {
for (std::size_t i = 0; i < arr.size() - 1; ++i) {
if (arr[i] > arr[i + 1]) {
return false;
}
}
return true;
}

请注意,为其他基于迭代器(arrayspanstring_view(的容器实现is_sorted可能需要C++20,因为在C++20之前没有ConstexprIterator这样的东西。

1看起来 gcc 和 clang 即使有-std=c++11也提供这些成员作为constexpr,所以如果这对你来说没问题,你可以使用其他两个答案之一。

不如其他解决方案好,但我想在 C++11 中证明这是可能的(即使很烦人((基于 @KonradRudolph 的解决方案构建(

编辑:这也只是C++14,因为从那时起std::getconstexpr。cppref上的页面一直令人困惑,但此后已修复。

#include <array>
#include <type_traits>
template<typename T, std::size_t N, std::size_t from>
constexpr typename std::enable_if<from == N, bool>::type
is_sorted_impl(std::array<T, N> const &arr)
{
return true;
}
template<typename T, std::size_t N, std::size_t from,
class = typename std::enable_if<from<N>::type> 
constexpr bool is_sorted_impl(std::array<T, N> const &arr)
{
return N - from == 0 or (std::get<from - 1>(arr) <= std::get<from>(arr) and
is_sorted_impl<T, N, from + 1>(arr));
}
template<typename T, std::size_t N>
constexpr bool is_sorted(std::array<T, N> const &arr)
{
return N == 0 or is_sorted_impl<T, N, 1>(arr);
}
int main()
{
constexpr std::array<int, 5> arr{1, 2, 3, 4, 5};
static_assert(is_sorted(arr), "test");
}

我们使用自 C++14 年推出以来constexprstd::get。为了解决实例化std::get<N>(这显然会给出编译时错误(,我们将函数模板专门用于from == N的情况(我们需要与enable_if一起做,因为不允许部分函数模板专用化(。不好,但有可能。

另一方面:@KonradRudolph的解决方案在 gcc 下编译,并且也使用-std=c++11 -pedantic进行 clang ,尽管由于operator[]constexpr,它不应该这是一个错误吗?

最新更新