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

如何在c++11中静态断言std::array类成员以进行排序?,c++,c++11,C++,C++11,在编译时,如何断言std::array类成员已排序?这将允许将其设置为const,使用静态断言,而不必在构造函数中调用std::sort 在c++20中,std::is_sorted已成为constepr,但在以前的版本中不可用;对于其他constexpr容器类型,使其更通用,留给读者作为练习: template <typename T, std::size_t N> constexpr bool is_sorted(std::array<T, N> const&

在编译时,如何断言std::array类成员已排序?这将允许将其设置为const,使用静态断言,而不必在构造函数中调用std::sort


在c++20中,std::is_sorted已成为constepr,但在以前的版本中不可用;对于其他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);
}

虽然没有其他解决方案那么好,但我想证明这是可能的,即使在基于@KonradRudolph的解决方案的C++11中也是如此

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

include是constexpr,因为它是在C++14中引入的。为了避免实例化std::get(这显然会导致编译时错误),我们专门化函数模板,以防from==N,如果不允许部分函数模板专门化,我们需要使用enable_。不太好,但有可能

另一方面:@KonradRudolph的解决方案在gcc和clang下编译,也使用-std=c++11-pedantic,尽管这不应该是因为操作符[]不是constexpr,这是一个bug吗?

免责声明:这需要c++14,因为正如我在评论中提到的,在C++14之前,您可能无法实现is_sorted for std::array的constepr版本,因为在C++11操作符[]/std::get中,std::array上的某些操作不是constepr1

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

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;
}
注意,实现是基于迭代器数组、span、string的其他容器排序的,视图可能需要C++20,因为C++20之前没有这样的东西


1即使使用-std=c++11,gcc和clang也会将这些成员作为constexpr提供,因此如果这对您合适,您可以使用其他两个答案中的一个。

您尝试了什么?constexpr的实现看起来并不复杂。但是,C++20标准库的源代码可能是可用的,因此您可以检查C++11解决方案是否不可能,因为运算符[]在C++11中不是constexpr,并且自C++17以来begin/end成员函数仅为constexpr。我对这个问题的答案无效,建议您只修改std::的代码。但是-正如@Holt所指出的,这是行不通的,因为std::array本身有一些非constexpr方法;任何涉及地址的事情都可能排除constexpr。所以-我很遗憾地同意@Holt。我不同意@Holt,请看我的回答与einpoklum的代码相比,我担心这不是尾部递归的。@Sneftel编译时执行引擎在调用constexpr函数之前是否执行尾部调用优化?我猜我对此表示怀疑,因为这是针对微小阵列的,所以效果无论如何都可以忽略不计。@Sneftel…但如果它困扰你,你当然可以交换最后两个条件项。嗯。涵盖此内容的内容被标记为已解决,并注明P0031R0,但我找不到相关的N文档,我不知道这是否意味着像某些发行状态一样对以前的出版物进行了更正。