Line data Source code
1 0 : // 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 1 : 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 1 : struct conforms_to 46 : : std::is_convertible<ConformingType*, ConformsTo<Protocol>*> {}; 47 : template <typename ConformingType, typename Protocol> 48 0 : constexpr bool conforms_to_v = conforms_to<ConformingType, Protocol>::value; 49 : /// @} 50 : 51 : /// @{ 52 : /*! 53 : * \ingroup ProtocolsGroup 54 : * \brief Assert that the `ConformingType` conforms to the `Protocol`. 55 : * 56 : * Similar to `tt::conforms_to`, but not SFINAE-friendly. Instead, triggers 57 : * static asserts with diagnostic messages to understand why the 58 : * `ConformingType` fails to conform to the `Protocol`. 59 : * 60 : * \see Documentation on \ref protocols 61 : * \see tt::conforms_to 62 : */ 63 : template <typename ConformingType, typename Protocol> 64 1 : struct assert_conforms_to : std::true_type { 65 : static_assert( 66 : tt::conforms_to_v<ConformingType, Protocol>, 67 : "The type does not indicate it conforms to the protocol. The type is " 68 : "listed as the first template parameter to `assert_conforms_to` " 69 : "and the protocol is listed as the second template parameter. " 70 : "Have you forgotten to (publicly) inherit the type from " 71 : "tt::ConformsTo<Protocol>?"); 72 : // Implicitly instantiate Protocol::test in order to test conformance 73 : static_assert( 74 : not std::is_same_v< 75 : decltype(typename Protocol::template test<ConformingType>{}), void>); 76 : }; 77 : 78 : template <typename ConformingType, typename Protocol> 79 0 : static constexpr bool assert_conforms_to_v = 80 : assert_conforms_to<ConformingType, Protocol>::value; 81 : /// @} 82 : 83 : } // namespace tt