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;
|