2020-02-18 11:23:21 +11:00
|
|
|
/*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* Copyright 2020, Danny Robson <danny@nerdcruft.net>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2022-03-18 12:38:30 +11:00
|
|
|
#include "concepts/named.hpp"
|
2020-02-18 11:23:21 +11:00
|
|
|
|
2022-03-18 12:38:30 +11:00
|
|
|
#include <concepts>
|
2020-02-24 14:38:42 +11:00
|
|
|
#include <tuple>
|
|
|
|
|
2022-03-18 12:38:30 +11:00
|
|
|
|
2020-02-18 11:23:21 +11:00
|
|
|
namespace cruft::concepts {
|
2020-02-27 12:21:37 +11:00
|
|
|
/// Tests if the type has all typedefs required for use with
|
|
|
|
/// std::iterator_traits.
|
|
|
|
template <typename T>
|
|
|
|
concept supports_iterator_traits = requires
|
|
|
|
{
|
|
|
|
typename T::difference_type;
|
|
|
|
typename T::value_type;
|
|
|
|
typename T::reference;
|
|
|
|
typename T::iterator_category;
|
|
|
|
|
|
|
|
// C++20 defines `pointer` as void if it's not present.
|
|
|
|
#if __cplusplus <= 201703L
|
|
|
|
typename T::pointer;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2020-03-16 14:12:04 +11:00
|
|
|
template <
|
|
|
|
typename ContainerT,
|
|
|
|
typename IndexT = std::size_t
|
|
|
|
>
|
|
|
|
concept supports_indexing = requires (ContainerT &t, IndexT idx) {
|
|
|
|
{ t[idx] };
|
|
|
|
};
|
2020-02-24 14:37:32 +11:00
|
|
|
|
2020-02-18 12:18:26 +11:00
|
|
|
|
|
|
|
/// A type that supports arithmetic operators.
|
|
|
|
template <typename T>
|
|
|
|
concept numeric = requires (T t)
|
|
|
|
{
|
2022-03-18 12:38:30 +11:00
|
|
|
{ t * t } -> std::convertible_to<T>;
|
|
|
|
{ t / t } -> std::convertible_to<T>;
|
|
|
|
{ t - t } -> std::convertible_to<T>;
|
|
|
|
{ t + t } -> std::convertible_to<T>;
|
2020-02-18 12:18:26 +11:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2020-02-24 14:37:32 +11:00
|
|
|
/// Anything that can be looped over using begin/end
|
2020-02-18 12:18:26 +11:00
|
|
|
template <typename T>
|
2020-02-24 14:37:32 +11:00
|
|
|
concept iterable = requires (T t)
|
|
|
|
{
|
2022-03-18 12:38:30 +11:00
|
|
|
{ std::begin (t) } -> named::legacy_iterator;
|
|
|
|
{ std::end (t) } -> named::legacy_iterator;
|
|
|
|
{ std::cbegin (t) } -> named::legacy_iterator;
|
|
|
|
{ std::cend (t) } -> named::legacy_iterator;
|
2020-02-24 14:37:32 +11:00
|
|
|
};
|
2020-02-24 14:38:42 +11:00
|
|
|
|
|
|
|
|
|
|
|
/// A class that supports tuple manipulators.
|
|
|
|
template <typename T>
|
|
|
|
concept tuple = requires (T a, T b)
|
|
|
|
{
|
2020-02-25 11:23:50 +11:00
|
|
|
// We should be checking this, but it fails for zero length tuples and
|
|
|
|
// it's kind of a low priority right now.
|
|
|
|
// { std::tuple_element<0,T> {} };
|
2022-03-18 12:38:30 +11:00
|
|
|
{ std::tuple_size<T>::value } -> std::convertible_to<std::size_t>;
|
2020-02-24 14:38:42 +11:00
|
|
|
{ std::tuple_cat (a, b) };
|
|
|
|
};
|
2022-03-18 12:38:30 +11:00
|
|
|
}
|