在编译时,如何断言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 中constexpr
1(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;
}
请注意,为其他基于迭代器(array
、span
、string_view
(的容器实现is_sorted
可能需要C++20,因为在C++20之前没有ConstexprIterator这样的东西。
1看起来 gcc 和 clang 即使有-std=c++11
也提供这些成员作为constexpr
,所以如果这对你来说没问题,你可以使用其他两个答案之一。
不如其他解决方案好,但我想在 C++11 中证明这是可能的(即使很烦人((基于 @KonradRudolph 的解决方案构建(
编辑:这也只是C++14,因为从那时起std::get
才constexpr
。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 年推出以来constexpr
std::get
。为了解决实例化std::get<N>
(这显然会给出编译时错误(,我们将函数模板专门用于from == N
的情况(我们需要与enable_if
一起做,因为不允许部分函数模板专用化(。不好,但有可能。
另一方面:@KonradRudolph的解决方案在 gcc 下编译,并且也使用-std=c++11 -pedantic
进行 clang ,尽管由于operator[]
不constexpr
,它不应该这是一个错误吗?