Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src/Progmasoft/Catch3/Internal/CompareTraits.hpp
blob: c18a4f888dc1460b1a446ea28af3f1699a83d300 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

//              Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
//   (See accompanying file LICENSE.txt or copy at
//        https://www.boost.org/LICENSE_1_0.txt)

// SPDX-License-Identifier: BSL-1.0
#pragma once

#include <Progmasoft/Catch3/Internal/VoidType.hpp>

#include <type_traits>

namespace Catch {
    namespace Detail {

#if defined( __GNUC__ ) && !defined( __clang__ )
#    pragma GCC diagnostic push
    // GCC likes to complain about comparing bool with 0, in the decltype()
    // that defines the comparable traits below.
#    pragma GCC diagnostic ignored "-Wbool-compare"
    // "ordered comparison of pointer with integer zero" same as above,
    // but it does not have a separate warning flag to suppress
#    pragma GCC diagnostic ignored "-Wextra"
    // Did you know that comparing floats with `0` directly
    // is super-duper dangerous in unevaluated context?
#    pragma GCC diagnostic ignored "-Wfloat-equal"
#endif

#if defined( __clang__ )
#    pragma clang diagnostic push
    // Did you know that comparing floats with `0` directly
    // is super-duper dangerous in unevaluated context?
#    pragma clang diagnostic ignored "-Wfloat-equal"
#endif

        // To avoid instantiating all of `is_foo_comparable<T, T&>`,
        // `is_foo_comparable<T&, T&>`, `is_foo_comparable<T, T>`, ...
        // we force the type into simple T ref. This does not cause behaviour
        // change, because the decomposer already only uses lvalues.
        //
        // Note that we do not strip away constness, as that would make
        // the comparability of `const T` dependent on comparability of `T`,
        // which could lead to behavior change from the current implementation.
        template <typename T>
        using IsComparableNormalized_t = std::remove_reference_t<T>&;

#define CATCH_DEFINE_COMPARABLE_TRAIT( id, op )                               \
    template <typename, typename, typename = void>                            \
    struct is_##id##_comparable_impl : std::false_type {};                    \
    template <typename T, typename U>                                         \
    struct is_##id##_comparable_impl<                                         \
        T,                                                                    \
        U,                                                                    \
        void_t<decltype( std::declval<T>() op std::declval<U>() )>>           \
        : std::true_type {};                                                  \
    template <typename T, typename U>                                         \
    using is_##id##_comparable =                                              \
        is_##id##_comparable_impl<IsComparableNormalized_t<T>,                \
                                  IsComparableNormalized_t<U>>;               \
    template <typename, typename = void>                                      \
    struct is_##id##_0_comparable_impl : std::false_type {};                  \
    template <typename T>                                                     \
    struct is_##id##_0_comparable_impl<                                       \
        T,                                                                    \
        void_t<decltype( std::declval<T>() op 0 )>>                           \
        : std::true_type {};                                                  \
    template <typename T>                                                     \
    using is_##id##_0_comparable =                                            \
        is_##id##_0_comparable_impl<IsComparableNormalized_t<T>>;

        // We need all 6 pre-spaceship comparison ops: <, <=, >, >=, ==, !=
        CATCH_DEFINE_COMPARABLE_TRAIT( lt, < )
        CATCH_DEFINE_COMPARABLE_TRAIT( le, <= )
        CATCH_DEFINE_COMPARABLE_TRAIT( gt, > )
        CATCH_DEFINE_COMPARABLE_TRAIT( ge, >= )
        CATCH_DEFINE_COMPARABLE_TRAIT( eq, == )
        CATCH_DEFINE_COMPARABLE_TRAIT( ne, != )

#undef CATCH_DEFINE_COMPARABLE_TRAIT

#if defined( __GNUC__ ) && !defined( __clang__ )
#    pragma GCC diagnostic pop
#endif
#if defined( __clang__ )
#    pragma clang diagnostic pop
#endif


    } // namespace Detail
} // namespace Catch