ProtocolHelpers.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <type_traits>
7 
8 #include "Utilities/TypeTraits.hpp"
9 
10 namespace tt {
11 
12 /*!
13  * \ingroup ProtocolsGroup
14  * \brief Indicate a class conforms to the `Protocol`.
15  *
16  * (Publicly) inherit classes from this class to indicate they conform to the
17  * `Protocol`.
18  *
19  * \see Documentation on \ref protocols
20  */
21 template <typename Protocol>
22 struct ConformsTo {};
23 
24 // Note that std::is_convertible is used in the following type aliases as it
25 // will not match private base classes (unlike std::is_base_of)
26 
27 // @{
28 /*!
29  * \ingroup ProtocolsGroup
30  * \brief Checks if the `ConformingType` conforms to the `Protocol`.
31  *
32  * This metafunction is SFINAE-friendly. See `tt::assert_conforms_to` for a
33  * metafunction that is not SFINAE-friendly but that triggers static asserts
34  * with diagnostic messages to understand why the `ConformingType` does not
35  * conform to the `Protocol`.
36  *
37  * This metafunction only checks if the class derives off the protocol to reduce
38  * compile time. Protocol conformance is tested rigorously in the unit tests
39  * instead.
40  *
41  * \see Documentation on \ref protocols
42  * \see tt::assert_conforms_to
43  */
44 template <typename ConformingType, typename Protocol>
45 using conforms_to =
47 template <typename ConformingType, typename Protocol>
48 constexpr bool conforms_to_v =
49  std::is_convertible_v<ConformingType*, ConformsTo<Protocol>*>;
50 // @}
51 
52 namespace detail {
53 
54 template <typename ConformingType, typename Protocol>
55 struct AssertConformsToImpl : std::true_type {
56  static_assert(
57  tt::conforms_to_v<ConformingType, Protocol>,
58  "The type does not indicate it conforms to the protocol. The type is "
59  "listed as the first template parameter to `assert_conforms_to` "
60  "and the protocol is listed as the second template parameter. "
61  "Have you forgotten to (publicly) inherit the type from "
62  "tt::ConformsTo<Protocol>?");
63  using test = typename Protocol::template test<ConformingType>;
64 };
65 
66 } // namespace detail
67 
68 /*!
69  * \ingroup ProtocolsGroup
70  * \brief Assert that the `ConformingType` conforms to the `Protocol`.
71  *
72  * Similar to `tt::conforms_to`, but not SFINAE-friendly. Instead, triggers
73  * static asserts with diagnostic messages to understand why the
74  * `ConformingType` fails to conform to the `Protocol`.
75  *
76  * \see Documentation on \ref protocols
77  * \see tt::conforms_to
78  */
79 template <typename ConformingType, typename Protocol>
80 static constexpr bool assert_conforms_to =
81  detail::AssertConformsToImpl<ConformingType, Protocol>::value;
82 
83 } // namespace tt
std::true_type
std::is_convertible
tt::conforms_to
typename std::is_convertible< ConformingType *, ConformsTo< Protocol > * > conforms_to
Checks if the ConformingType conforms to the Protocol.
Definition: ProtocolHelpers.hpp:46
tt
Definition: TensorExpression.hpp:113
tt::ConformsTo
Indicate a class conforms to the Protocol.
Definition: ProtocolHelpers.hpp:22
type_traits