]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/include/boost/hana/fwd/core/tag_of.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / hana / include / boost / hana / fwd / core / tag_of.hpp
1 /*!
2 @file
3 Forward declares `boost::hana::tag_of` and `boost::hana::tag_of_t`.
4
5 @copyright Louis Dionne 2013-2016
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 */
9
10 #ifndef BOOST_HANA_FWD_CORE_TAG_OF_HPP
11 #define BOOST_HANA_FWD_CORE_TAG_OF_HPP
12
13 #include <boost/hana/config.hpp>
14
15
16 BOOST_HANA_NAMESPACE_BEGIN
17 //! @ingroup group-core
18 //! %Metafunction returning the tag associated to `T`.
19 //!
20 //! There are several ways to specify the tag of a C++ type. If it's a
21 //! user-defined type, one can define a nested `hana_tag` alias:
22 //! @code
23 //! struct MyUserDefinedType {
24 //! using hana_tag = MyTag;
25 //! };
26 //! @endcode
27 //!
28 //! Sometimes, however, the C++ type can't be modified (if it's in a
29 //! foreign library) or simply can't have nested types (if it's not a
30 //! struct or class). In those cases, using a nested alias is impossible
31 //! and so ad-hoc customization is also supported by specializing
32 //! `tag_of` in the `boost::hana` namespace:
33 //! @code
34 //! struct i_cant_modify_this;
35 //!
36 //! namespace boost { namespace hana {
37 //! template <>
38 //! struct tag_of<i_cant_modify_this> {
39 //! using type = MyTag;
40 //! };
41 //! }}
42 //! @endcode
43 //!
44 //! `tag_of` can also be specialized for all C++ types satisfying some
45 //! boolean condition using `when`. `when` accepts a single compile-time
46 //! boolean and enables the specialization of `tag_of` if and only if
47 //! that boolean is `true`. This is similar to the well known C++ idiom
48 //! of using a dummy template parameter with `std::enable_if` and relying
49 //! on SFINAE. For example, we could specify the tag of all
50 //! `fusion::vector`s by doing:
51 //! @code
52 //! struct BoostFusionVector;
53 //!
54 //! namespace boost { namespace hana {
55 //! template <typename T>
56 //! struct tag_of<T, when<
57 //! std::is_same<
58 //! typename fusion::traits::tag_of<T>::type,
59 //! fusion::traits::tag_of<fusion::vector<>>::type
60 //! >{}
61 //! >> {
62 //! using type = BoostFusionVector;
63 //! };
64 //! }}
65 //! @endcode
66 //!
67 //! Also, when it is not specialized and when the given C++ type does not
68 //! have a nested `hana_tag` alias, `tag_of<T>` returns `T` itself. This
69 //! makes tags a simple extension of normal C++ types. This is _super_
70 //! useful, mainly for two reasons. First, this allows Hana to adopt a
71 //! reasonable default behavior for some operations involving types that
72 //! have no notion of tags. For example, Hana allows comparing with `equal`
73 //! any two objects for which a valid `operator==` is defined, and that
74 //! without any work on the user side. Second, it also means that you can
75 //! ignore tags completely if you don't need their functionality; just use
76 //! the normal C++ type of your objects and everything will "just work".
77 //!
78 //! Finally, also note that `tag_of<T>` is always equivalent to `tag_of<U>`,
79 //! where `U` is the type `T` after being stripped of all references and
80 //! cv-qualifiers. This makes it unnecessary to specialize `tag_of` for
81 //! all reference and cv combinations, which would be a real pain. Also,
82 //! `tag_of` is required to be idempotent. In other words, it must always
83 //! be the case that `tag_of<tag_of<T>::%type>::%type` is equivalent to
84 //! `tag_of<T>::%type`.
85 //!
86 //! > __Tip 1__\n
87 //! > If compile-time performance is a serious concern, consider
88 //! > specializing the `tag_of` metafunction in Hana's namespace.
89 //! > When unspecialized, the metafunction has to use SFINAE, which
90 //! > tends to incur a larger compile-time overhead. For heavily used
91 //! > templated types, this can potentially make a difference.
92 //!
93 //! > __Tip 2__\n
94 //! > Consider using `tag_of_t` alias instead of `tag_of`, which
95 //! > reduces the amount of typing in dependent contexts.
96 //!
97 //!
98 //! Example
99 //! -------
100 //! @include example/core/tag_of.cpp
101 #ifdef BOOST_HANA_DOXYGEN_INVOKED
102 template <typename T, optional when-based enabler>
103 struct tag_of { unspecified };
104 #else
105 template <typename T, typename = void>
106 struct tag_of;
107 #endif
108
109 //! @ingroup group-core
110 //! Alias to `tag_of<T>::%type`, provided for convenience.
111 //!
112 //!
113 //! Example
114 //! -------
115 //! @include example/core/tag_of_t.cpp
116 template <typename T>
117 using tag_of_t = typename hana::tag_of<T>::type;
118 BOOST_HANA_NAMESPACE_END
119
120 #endif // !BOOST_HANA_FWD_CORE_TAG_OF_HPP