Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines class TypeDisplayer
6 :
7 : #pragma once
8 :
9 : #include "Utilities/TMPL.hpp"
10 :
11 : /*!
12 : * \ingroup UtilitiesGroup TypeTraitsGroup
13 : * \brief Get compiler error with type of template parameter
14 : *
15 : * The compiler error generated when using an object of type
16 : * `TypeDisplayer<...>` contains the types of the template parameters. This
17 : * effectively provides printf-debugging for metaprogramming. For example,
18 : * \code
19 : * TypeDisplayer<std::vector<double>> some_random_name;
20 : * \endcode
21 : * will produce a compiler error that contains the type `std::vector<double,
22 : * std::allocator...>`. TypeDisplayer is extremely useful when debugging
23 : * template metaprograms.
24 : *
25 : * \note The TypeDisplayer header should only be included during testing
26 : * and debugging.
27 : *
28 : * \see make_list
29 : */
30 : template <typename...>
31 1 : struct TypeDisplayer;
32 :
33 : /*!
34 : * \ingroup UtilitiesGroup
35 : * \brief Metafunction to turn a parameter pack into a typelist
36 : *
37 : * This metafunction is really only useful for debugging metaprograms. For
38 : * example, the desired algorithm might be:
39 : *
40 : * \code
41 : * using variables_tags_from_single_tags = tmpl::filter<
42 : * extracted_from_variables,
43 : * tmpl::bind<tmpl::found, tmpl::pin<mutated_tags_list>,
44 : * tmpl::bind<std::is_same, tmpl::_1, tmpl::parent<tmpl::_1>>>>;
45 : * \endcode
46 : *
47 : * However, getting the `tmpl::pin`, `tmpl::parent`, and `tmpl::bind` calls
48 : * right can be extremely frustrating with little help as to what is going on.
49 : * Let's introduce an error by pinning `tmpl::_1`:
50 : *
51 : * \code
52 : * using variables_tags_from_single_tags = tmpl::filter<
53 : * extracted_from_variables,
54 : * tmpl::bind<tmpl::found, tmpl::pin<mutated_tags_list>,
55 : * tmpl::bind<std::is_same, tmpl::pin<tmpl::_1>,
56 : * tmpl::parent<tmpl::_1>>>>;
57 : * \endcode
58 : *
59 : * The result is comparing all values in `extracted_from_variables` to
60 : * themselves. To find this out, replace `tmpl::filter` and `tmpl::found` with
61 : * `tmpl::transform`, and the metafunction `std::is_same` to `make_list`.
62 : * You will then get back a "backtrace" of what the algorithm did, which is
63 : * invaluable for getting the `tmpl::pin` and `tmpl::parent` right. That is,
64 : *
65 : * \code
66 : * using variables_tags_from_single_tags2 = tmpl::transform<
67 : * extracted_from_variables,
68 : * tmpl::bind<tmpl::transform, tmpl::pin<mutated_tags_list>,
69 : * tmpl::bind<make_list, tmpl::_1, tmpl::parent<tmpl::_1>>>>;
70 : *
71 : * TypeDisplayer<variables_tags_from_single_tags2> aeou;
72 : * \endcode
73 : *
74 : * You will get an output along the lines of:
75 : *
76 : * \code
77 : * src/DataStructures/DataBox.hpp:1181:40: error: implicit instantiation of
78 : * undefined template
79 : * 'TypeDisplayer<brigand::list<brigand::list<
80 : * brigand::list<test_databox_tags::ScalarTag,
81 : * test_databox_tags::Tag0>, brigand::list<test_databox_tags::ScalarTag,
82 : * Tags::Variables<brigand::list<test_databox_tags::ScalarTag,
83 : * test_databox_tags::VectorTag> > > >,
84 : * brigand::list<brigand::list<test_databox_tags::VectorTag,
85 : * test_databox_tags::Tag0>,
86 : * brigand::list<test_databox_tags::VectorTag,
87 : * Tags::Variables<
88 : * brigand::list<test_databox_tags::ScalarTag,
89 : * test_databox_tags::VectorTag> > > > > >'
90 : * \endcode
91 : *
92 : * \see TypeDisplayer
93 : */
94 : template <class... Ts>
95 1 : struct make_list {
96 0 : using type = tmpl::list<Ts...>;
97 : };
|