mirror of
https://github.com/boostorg/stl_interfaces.git
synced 2025-05-12 14:11:41 +00:00
Add static_assert macros, use them in the tests and examples, and add docs for
them.
This commit is contained in:
parent
b7fea24984
commit
c0e571d034
@ -45,6 +45,9 @@
|
||||
[def _Facade_ Boost.IteratorFacade]
|
||||
[def _iter_facade_ [classref boost::iterator_facade::iterator_facade `iterator_facade`]]
|
||||
|
||||
[def _concept_m_ [macroref BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT]]
|
||||
[def _traits_m_ [macroref BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS]]
|
||||
|
||||
[def _CRTP_ [@https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern CRTP]]
|
||||
[def _Iterator_ [@https://www.boost.org/doc/libs/release/libs/iterator/doc/index.html Boost.Iterator]]
|
||||
|
||||
|
@ -219,4 +219,7 @@ Consider this good code hygiene. Without this simple check, you'll probably
|
||||
eventually find yourself looking at an error message with a very long template
|
||||
instantiation stack.
|
||||
|
||||
There's also a macro that can help you check that `std::iterator_traits` is
|
||||
well-formed and provides the corect types. See _traits_m_.
|
||||
|
||||
[endsect]
|
||||
|
@ -47,10 +47,11 @@ private:
|
||||
};
|
||||
//]
|
||||
|
||||
//[ node_iterator_concept_check
|
||||
#if 201703L < __cplusplus
|
||||
static_assert(std::forward_iterator<node_iterator>);
|
||||
#endif
|
||||
//[ node_iterator_concept_check Equivalent to
|
||||
// static_assert(std::forward_iterator<node_iterator>), or nothing in C++17
|
||||
// and earlier.
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
node_iterator, std::forward_iterator)
|
||||
//]
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@ template<typename BidiIter>
|
||||
struct reverse_iterator
|
||||
: boost::iterator_facade::iterator_facade<
|
||||
reverse_iterator<BidiIter>,
|
||||
#if 201703L < __cplusplus
|
||||
#if 201703L < __cplusplus && defined(__cpp_lib_ranges)
|
||||
typename std::iterator_traits<BidiIter>::iterator_concept,
|
||||
#else
|
||||
typename std::iterator_traits<BidiIter>::iterator_category,
|
||||
|
@ -333,8 +333,6 @@ namespace boost { namespace iterator_facade {
|
||||
// TODO: Compile-fail tests and associated static_asserts in these
|
||||
// specializations to help catch common errors.
|
||||
|
||||
// TODO: Tests that cover iterator_traits for uses of these facades.
|
||||
|
||||
/** A specialization of iterator_facade specific to output iterators. */
|
||||
template<
|
||||
typename Derived,
|
||||
@ -861,4 +859,81 @@ namespace boost { namespace iterator_facade {
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#ifdef BOOST_ITERATOR_FACADE_DOXYGEN
|
||||
|
||||
/** `static_asserts` that iterator type `iter` models concept `concept_name`.
|
||||
This is useful for checking that an iterator you write using
|
||||
`iterator_facade` models the right C++ concept.
|
||||
|
||||
For example: `BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(my_iter,
|
||||
std::input_iterator)`.
|
||||
|
||||
\note This macro exapnds to nothing when `__cpp_lib_concepts` is not
|
||||
defined. */
|
||||
#define BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(iter, concept_name)
|
||||
|
||||
/** `static_asserts` that the types of all typedefs in
|
||||
`std::iterator_traits<iter>` match the remaining macro parameters. This
|
||||
is useful for checking that an iterator you write using `iterator_facade`
|
||||
has the correct iterator traits.
|
||||
|
||||
For example: `BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(my_iter,
|
||||
std::input_iterator_tag, std::input_iterator_tag, int, int &, int *, std::ptrdiff_t)`.
|
||||
|
||||
\note This macro ignores the `concept` parameter when `__cpp_lib_concepts`
|
||||
is not defined. */
|
||||
#define BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS( \
|
||||
iter, category, concept, value_type, reference, pointer, difference_type)
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL( \
|
||||
iter, concept_name) \
|
||||
static_assert(concept_name<iter>);
|
||||
|
||||
#if 201703L < __cplusplus && defined(__cpp_lib_concepts)
|
||||
#define BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(iter, concept_name) \
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL( \
|
||||
iter, concept_name)
|
||||
#else
|
||||
#define BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(iter, concept_name)
|
||||
#endif
|
||||
|
||||
#define BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
|
||||
iter, category, value_t, ref, ptr, diff_t) \
|
||||
static_assert(std::is_same< \
|
||||
typename std::iterator_traits<iter>::iterator_category, \
|
||||
category>::value); \
|
||||
static_assert(std::is_same< \
|
||||
typename std::iterator_traits<iter>::value_type, \
|
||||
value_t>::value); \
|
||||
static_assert( \
|
||||
std::is_same<typename std::iterator_traits<iter>::reference, ref>:: \
|
||||
value); \
|
||||
static_assert( \
|
||||
std::is_same<typename std::iterator_traits<iter>::pointer, ptr>:: \
|
||||
value); \
|
||||
static_assert(std::is_same< \
|
||||
typename std::iterator_traits<iter>::difference_type, \
|
||||
diff_t>::value);
|
||||
|
||||
#if 201703L < __cplusplus && defined(__cpp_lib_ranges)
|
||||
#define BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS( \
|
||||
iter, category, concept, value_type, reference, pointer, difference_type) \
|
||||
static_assert(std::is_same< \
|
||||
typename std::iterator_traits<iter>::iterator_concept, \
|
||||
concept>::value); \
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
|
||||
iter, category, value_type, reference, pointer, difference_type)
|
||||
#else
|
||||
#define BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS( \
|
||||
iter, category, concept, value_type, reference, pointer, difference_type) \
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
|
||||
iter, category, value_type, reference, pointer, difference_type)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -33,6 +33,17 @@ private:
|
||||
int * it_;
|
||||
};
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
basic_bidirectional_iter, std::bidirectional_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
basic_bidirectional_iter,
|
||||
std::bidirectional_iterator_tag,
|
||||
std::bidirectional_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
int *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
template<typename ValueType>
|
||||
struct bidirectional_iter : boost::iterator_facade::iterator_facade<
|
||||
bidirectional_iter<ValueType>,
|
||||
@ -65,6 +76,28 @@ private:
|
||||
using bidirectional = bidirectional_iter<int>;
|
||||
using const_bidirectional = bidirectional_iter<int const>;
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
bidirectional, std::bidirectional_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
bidirectional,
|
||||
std::bidirectional_iterator_tag,
|
||||
std::bidirectional_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
int *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
const_bidirectional, std::bidirectional_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
const_bidirectional,
|
||||
std::bidirectional_iterator_tag,
|
||||
std::bidirectional_iterator_tag,
|
||||
int const,
|
||||
int const &,
|
||||
int const *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
#if 0 // TODO: Call ranges algorithms with this.
|
||||
struct basic_proxy_bidirectional_iter : boost::iterator_facade::iterator_facade<
|
||||
basic_proxy_bidirectional_iter,
|
||||
|
@ -28,6 +28,17 @@ private:
|
||||
int * it_;
|
||||
};
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
basic_forward_iter, std::forward_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
basic_forward_iter,
|
||||
std::forward_iterator_tag,
|
||||
std::forward_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
int *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
template<typename ValueType>
|
||||
struct forward_iter : boost::iterator_facade::iterator_facade<
|
||||
forward_iter<ValueType>,
|
||||
@ -59,6 +70,28 @@ private:
|
||||
using forward = forward_iter<int>;
|
||||
using const_forward = forward_iter<int const>;
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
forward, std::forward_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
forward,
|
||||
std::forward_iterator_tag,
|
||||
std::forward_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
int *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
const_forward, std::forward_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
const_forward,
|
||||
std::forward_iterator_tag,
|
||||
std::forward_iterator_tag,
|
||||
int const,
|
||||
int const &,
|
||||
int const *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
#if 0 // TODO: Call ranges algorithms with this.
|
||||
struct basic_proxy_forward_iter : boost::iterator_facade::iterator_facade<
|
||||
basic_proxy_forward_iter,
|
||||
|
@ -28,6 +28,17 @@ private:
|
||||
int * it_;
|
||||
};
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
basic_input_iter, std::input_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
basic_input_iter,
|
||||
std::input_iterator_tag,
|
||||
std::input_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
int *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
template<typename ValueType>
|
||||
struct input_iter : boost::iterator_facade::iterator_facade<
|
||||
input_iter<ValueType>,
|
||||
@ -56,6 +67,17 @@ private:
|
||||
friend struct input_iter;
|
||||
};
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
input_iter<int>, std::input_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
input_iter<int>,
|
||||
std::input_iterator_tag,
|
||||
std::input_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
int *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
using int_input = input_iter<int>;
|
||||
using const_int_input = input_iter<int const>;
|
||||
using pair_input = input_iter<std::pair<int, int>>;
|
||||
@ -89,6 +111,18 @@ private:
|
||||
friend struct proxy_input_iter;
|
||||
};
|
||||
|
||||
using int_pair = std::pair<int, int>;
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
proxy_input_iter<int_pair>, std::input_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
proxy_input_iter<int_pair>,
|
||||
std::input_iterator_tag,
|
||||
std::input_iterator_tag,
|
||||
int_pair,
|
||||
int_pair,
|
||||
boost::iterator_facade::proxy_arrow_result<int_pair>,
|
||||
std::ptrdiff_t)
|
||||
|
||||
std::array<int, 10> ints = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
|
||||
std::array<std::pair<int, int>, 10> pairs = {{
|
||||
{0, 1},
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
struct basic_output_iter
|
||||
: boost::iterator_facade::
|
||||
iterator_facade<basic_output_iter, std::input_iterator_tag, int>
|
||||
iterator_facade<basic_output_iter, std::output_iterator_tag, int>
|
||||
{
|
||||
basic_output_iter() : it_(nullptr) {}
|
||||
basic_output_iter(int * it) : it_(it) {}
|
||||
@ -29,6 +29,16 @@ private:
|
||||
|
||||
using output = basic_output_iter;
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(output, std::output_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
output,
|
||||
std::output_iterator_tag,
|
||||
std::output_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
void,
|
||||
std::ptrdiff_t)
|
||||
|
||||
template<typename Container>
|
||||
struct back_insert_iter : boost::iterator_facade::iterator_facade<
|
||||
back_insert_iter<Container>,
|
||||
@ -60,6 +70,16 @@ private:
|
||||
|
||||
using back_insert = back_insert_iter<std::vector<int>>;
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(back_insert, std::output_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
back_insert,
|
||||
std::output_iterator_tag,
|
||||
std::output_iterator_tag,
|
||||
int,
|
||||
back_insert &,
|
||||
void,
|
||||
std::ptrdiff_t)
|
||||
|
||||
|
||||
std::vector<int> ints = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
|
||||
|
||||
|
@ -32,6 +32,17 @@ private:
|
||||
int * it_;
|
||||
};
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
basic_random_access_iter, std::random_access_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
basic_random_access_iter,
|
||||
std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
int *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
template<typename ValueType>
|
||||
struct random_access_iter : boost::iterator_facade::iterator_facade<
|
||||
random_access_iter<ValueType>,
|
||||
@ -63,6 +74,28 @@ private:
|
||||
using random_access = random_access_iter<int>;
|
||||
using const_random_access = random_access_iter<int const>;
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
random_access, std::random_access_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
random_access,
|
||||
std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag,
|
||||
int,
|
||||
int &,
|
||||
int *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
const_random_access, std::random_access_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
const_random_access,
|
||||
std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag,
|
||||
int const,
|
||||
int const &,
|
||||
int const *,
|
||||
std::ptrdiff_t)
|
||||
|
||||
// TODO: Call ranges algorithms with this.
|
||||
struct zip_iter : boost::iterator_facade::proxy_iterator_facade<
|
||||
zip_iter,
|
||||
@ -93,6 +126,20 @@ private:
|
||||
int * it2_;
|
||||
};
|
||||
|
||||
using int_pair = std::tuple<int, int>;
|
||||
using int_refs_pair = std::tuple<int &, int &>;
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
zip_iter, std::random_access_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
zip_iter,
|
||||
std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag,
|
||||
int_pair,
|
||||
int_refs_pair,
|
||||
boost::iterator_facade::proxy_arrow_result<int_refs_pair>,
|
||||
std::ptrdiff_t)
|
||||
|
||||
struct int_t
|
||||
{
|
||||
int value_;
|
||||
@ -139,6 +186,20 @@ private:
|
||||
int * it2_;
|
||||
};
|
||||
|
||||
using int_t_int_pair = std::tuple<int_t, int>;
|
||||
using int_t_int_refs_pair = std::tuple<int_t &, int &>;
|
||||
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_CONCEPT(
|
||||
udt_zip_iter, std::random_access_iterator)
|
||||
BOOST_ITERATOR_FACADE_STATIC_ASSERT_ITERATOR_TRAITS(
|
||||
udt_zip_iter,
|
||||
std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag,
|
||||
int_t_int_pair,
|
||||
int_t_int_refs_pair,
|
||||
boost::iterator_facade::proxy_arrow_result<int_t_int_refs_pair>,
|
||||
std::ptrdiff_t)
|
||||
|
||||
namespace std {
|
||||
// Required for std::sort to work with zip_iter. If zip_iter::reference
|
||||
// were not a std::tuple with builtin types as its template parameters, we
|
||||
|
Loading…
x
Reference in New Issue
Block a user