[英]How to can a std::array class member be statically asserted to be sorted in c++11?
How can it be asserted, during compile time, that a std::array<uint8_t, 3>
class member is sorted?在编译期间,如何断言std::array<uint8_t, 3>
类成员已排序? This would allow it to be made const
, use a static_assert()
and not have to call std::sort()
in the constructor.这将允许它成为const
,使用static_assert()
而不必在构造函数中调用std::sort()
。
In c++20 std::is_sorted()
has become a constexpr, but is not available for prior versions.在 c++20 中std::is_sorted()
已成为 constexpr,但不适用于以前的版本。
Here's a proof of concept implementation that can be called directly on a std::array
;这是一个可以直接在std::array
上调用的概念实现证明; making this more general (for other constexpr container types) is left as an exercise to the reader:使这更通用(对于其他 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);
}
Disclaimer: This requires C++14, since, as I have mentioned in the comments, you probably cannot implement a constexpr
version of is_sorted
for std::array
prior to C++14 due to some operations on std::array
not being constexpr
1 in C++11 ( operator[]
/ std::get<>
).免责声明:这需要 C++14,因为正如我在评论中提到的,由于std::array
上的某些操作没有被执行,您可能无法在 C++14 之前为std::array
实现is_sorted
的constexpr
版本C++11 中的constexpr
1 ( operator[]
/ std::get<>
)。
With a C++14 implementation, you can use a standard for
-loop in your constexpr
function and use this very simple implementation:使用 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;
}
Note that implementing is_sorted
for other containers based on iterators ( array
, span
, string_view
) probably requires C++20 since there are no such things as ConstexprIterator prior to C++20.请注意,为基于迭代器( array
、 span
、 string_view
)的其他容器实现is_sorted
可能需要 C++20,因为在 C++20 之前没有ConstexprIterator这样的东西。
1 It looks like gcc and clang provide these members as constexpr
even with -std=c++11
, so if this is okay for you, you can use one of the two other answers. 1即使使用-std=c++11
,看起来 gcc 和 clang 也将这些成员作为constexpr
提供,所以如果这对您来说没问题,您可以使用其他两个答案之一。
Not as nice as the other solution, but I wanted to show that this is possible (even if annoyingly so) in C++11 (building on @KonradRudolph's solution)不像其他解决方案那么好,但我想表明在 C++11 中这是可能的(即使很烦人)(建立在@KonradRudolph 的解决方案上)
Edit: This is also just C++14, since std::get
is only constexpr
since then.编辑:这也只是 C++14,因为从那时起std::get
只是constexpr
。 The page on it on cppref has been confusing but has since then be fixed. 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");
}
We use std::get
which was constexpr
since it was introduced in C++14.我们使用std::get
,它是constexpr
因为它是在 C++14 中引入的。 To get around instantiating the std::get<N>
(which gives obviously a compile time error) we specialize the function template for the case that from == N
(which we need to do with enable_if
since partial function template specializations are not allowed).为了避免实例化std::get<N>
(这显然会导致编译时错误),我们专门针对from == N
的情况使用函数模板(我们需要使用enable_if
因为不允许部分函数模板特化)。 Not nice, but possible.不太好,但可能。
On another note: @KonradRudolph's solution compiles under gcc and clang also with -std=c++11 -pedantic
, altough it should not due to the operator[]
not being constexpr
is this a bug?另请注意:@KonradRudolph 的解决方案在 gcc 和 clang 下编译,也使用-std=c++11 -pedantic
,虽然它不应该是由于operator[]
不是constexpr
这是一个错误?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.