Line data Source code
1 1 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : /// \file 7 : /// Defines the type alias Requires 8 : 9 : #include <cstddef> 10 : 11 : namespace Requires_detail { 12 : template <bool B> 13 : struct requires_impl { 14 : using template_error_type_failed_to_meet_requirements_on_template_parameters = 15 : std::nullptr_t; 16 : }; 17 : 18 : template <> 19 : struct requires_impl<false> {}; 20 : } // namespace Requires_detail 21 : 22 : /*! 23 : * \ingroup UtilitiesGroup 24 : * \brief Express requirements on the template parameters of a function or 25 : * class, replaces `std::enable_if_t` 26 : * 27 : * Replacement for `std::enable_if_t` and Concepts for expressing requirements 28 : * on template parameters. This does not require merging of the Concepts 29 : * TS (whose merit is debatable) and provides an "error message" if substitution 30 : * of a template parameter failed. Specifically, the compiler error will contain 31 : * "template_error_type_failed_to_meet_requirements_on_template_parameters", 32 : * aiding the user of a function or class in tracking down the list of 33 : * requirements on the deduced type. 34 : * 35 : * For example, if a function `foo` is defined as: 36 : * \snippet Utilities/Test_Requires.cpp foo_definition 37 : * then calling the function with a list, `foo(std::list<double>{});` results in 38 : * the following compilation error from clang: 39 : * \code 40 : * ./tests/Unit/Utilities/Test_Requires.cpp:29:3: error: no matching function 41 : * for call to 'foo' 42 : * foo(std::list<double>{}); 43 : * ^~~ 44 : * ./tests/Unit/Utilities/Test_Requires.cpp:15:13: note: candidate 45 : * template ignored: substitution failure [with T = std::__1::list<double, 46 : * std::__1::allocator<double> >]: no type named 47 : * 'template_error_type_failed_to_meet_requirements_on_template_parameters' 48 : * in 'Requires_detail::requires_impl<false>' 49 : * std::string foo(const T&) { 50 : * ^ 51 : * 1 error generated. 52 : * \endcode 53 : * 54 : * Here is an example of how write function overloads using `Requires` or to 55 : * express constraints on the template parameters: 56 : * \snippet Utilities/Test_Requires.cpp function_definitions 57 : * 58 : * \note 59 : * Using `Requires` is safer than using `std::enable_if_t` because the 60 : * nested type alias is of type `std::nullptr_t` and so usage is always: 61 : * \code 62 : * template <typename T, Requires<(bool depending on T)> = nullptr> 63 : * \endcode 64 : */ 65 : template <bool B> 66 1 : using Requires = typename Requires_detail::requires_impl< 67 : B>::template_error_type_failed_to_meet_requirements_on_template_parameters;