Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:49

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     alias.h
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 
0008 #ifndef BOOST_HOF_GUARD_ALIAS_H
0009 #define BOOST_HOF_GUARD_ALIAS_H
0010 
0011 #include <boost/hof/returns.hpp>
0012 #include <boost/hof/detail/delegate.hpp>
0013 #include <boost/hof/detail/move.hpp>
0014 #include <boost/hof/detail/holder.hpp>
0015 #include <boost/hof/config.hpp>
0016 
0017 /// alias
0018 /// =====
0019 /// 
0020 /// Description
0021 /// -----------
0022 /// 
0023 /// The `alias` class wraps a type with a new type that can be tagged by the
0024 /// user. This allows defining extra attributes about the type outside of the
0025 /// type itself. There are three different ways the value can be stored: as a
0026 /// member variable, by inheritance, or as a static member variable. The value
0027 /// can be retrieved uniformily using the `alias_value` function.
0028 /// 
0029 /// Synopsis
0030 /// --------
0031 /// 
0032 ///     // Alias the type using a member variable
0033 ///     template<class T, class Tag=void>
0034 ///     class alias;
0035 /// 
0036 ///     // Alias the type by inheriting
0037 ///     template<class T, class Tag=void>
0038 ///     class alias_inherit;
0039 /// 
0040 ///     // Alias the type using a static variable
0041 ///     template<class T, class Tag=void>
0042 ///     class alias_static;
0043 /// 
0044 ///     // Retrieve tag from alias
0045 ///     template<class Alias>
0046 ///     class alias_tag;
0047 /// 
0048 ///     // Check if type has a certian tag
0049 ///     template<class T, class Tag>
0050 ///     class has_tag;
0051 /// 
0052 ///     // Retrieve value from alias
0053 ///     template<class Alias>
0054 ///     constexpr auto alias_value(Alias&&);
0055 /// 
0056 
0057 #ifdef _MSC_VER
0058 #pragma warning(push)
0059 #pragma warning(disable: 4579)
0060 #endif
0061 
0062 namespace boost { namespace hof {
0063 
0064 template<class T>
0065 struct alias_tag;
0066 
0067 template<class T, class Tag, class=void>
0068 struct has_tag
0069 : std::false_type
0070 {};
0071 
0072 template<class T, class Tag>
0073 struct has_tag<T, Tag, typename detail::holder<
0074     typename alias_tag<T>::type
0075 >::type>
0076 : std::is_same<typename alias_tag<T>::type, Tag>
0077 {};
0078 
0079 namespace detail {
0080 
0081 template<class T>
0082 constexpr T& lvalue(T& x) noexcept
0083 {
0084     return x;
0085 }
0086 
0087 template<class T>
0088 constexpr const T& lvalue(const T& x) noexcept
0089 {
0090     return x;
0091 }
0092 
0093 }
0094 
0095 #define BOOST_HOF_UNARY_PERFECT_FOREACH(m) \
0096     m(const&, boost::hof::detail::lvalue) \
0097     m(&, boost::hof::detail::lvalue) \
0098     m(&&, boost::hof::move) \
0099 
0100 template<class T, class Tag=void>
0101 struct alias
0102 {
0103     T value;
0104     BOOST_HOF_DELEGATE_CONSTRUCTOR(alias, T, value)
0105 };
0106 
0107 #define BOOST_HOF_DETAIL_ALIAS_GET_VALUE(ref, move) \
0108 template<class Tag, class T, class... Ts> \
0109 constexpr auto alias_value(alias<T, Tag> ref a, Ts&&...) BOOST_HOF_RETURNS(move(a.value))
0110 BOOST_HOF_UNARY_PERFECT_FOREACH(BOOST_HOF_DETAIL_ALIAS_GET_VALUE)
0111 
0112 template<class T, class Tag>
0113 struct alias_tag<alias<T, Tag>>
0114 { typedef Tag type; };
0115 
0116 
0117 template<class T, class Tag=void>
0118 struct alias_inherit 
0119 #if (defined(__GNUC__) && !defined (__clang__))
0120 : std::conditional<(std::is_class<T>::value), T, alias<T>>::type
0121 #else
0122 : T
0123 #endif
0124 {
0125     BOOST_HOF_INHERIT_CONSTRUCTOR(alias_inherit, T)
0126 };
0127 
0128 #define BOOST_HOF_DETAIL_ALIAS_INHERIT_GET_VALUE(ref, move) \
0129 template<class Tag, class T, class... Ts, class=typename std::enable_if<(BOOST_HOF_IS_CLASS(T))>::type> \
0130 constexpr T ref alias_value(alias_inherit<T, Tag> ref a, Ts&&...) BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(move(a)) \
0131 { \
0132     return move(a); \
0133 }
0134 BOOST_HOF_UNARY_PERFECT_FOREACH(BOOST_HOF_DETAIL_ALIAS_INHERIT_GET_VALUE)
0135 
0136 template<class T, class Tag>
0137 struct alias_tag<alias_inherit<T, Tag>>
0138 { typedef Tag type; };
0139 
0140 namespace detail {
0141 
0142 template<class T, class Tag>
0143 struct alias_static_storage
0144 {
0145 #ifdef _MSC_VER
0146     // Since we disable the error for 4579 on MSVC, which leaves the static
0147     // member unitialized at runtime, it is, therefore, only safe to use this
0148     // class on types that are empty with constructors that have no possible
0149     // side effects.
0150     static_assert(BOOST_HOF_IS_EMPTY(T) && 
0151         BOOST_HOF_IS_LITERAL(T) && 
0152         BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(T), "In-class initialization is not yet implemented on MSVC");
0153 #endif
0154     static constexpr T value = T();
0155 };
0156 
0157 template<class T, class Tag>
0158 constexpr T alias_static_storage<T, Tag>::value;
0159 
0160 }
0161 
0162 template<class T, class Tag=void>
0163 struct alias_static
0164 {
0165     template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
0166     constexpr alias_static(Ts&&...) noexcept
0167     {}
0168 };
0169 
0170 template<class Tag, class T, class... Ts>
0171 constexpr const T& alias_value(const alias_static<T, Tag>&, Ts&&...) noexcept
0172 {
0173     return detail::alias_static_storage<T, Tag>::value;
0174 }
0175 
0176 template<class T, class Tag>
0177 struct alias_tag<alias_static<T, Tag>>
0178 { typedef Tag type; };
0179 
0180 namespace detail {
0181 
0182 template<class T, class Tag>
0183 struct alias_try_inherit
0184 : std::conditional<(BOOST_HOF_IS_CLASS(T) && !BOOST_HOF_IS_FINAL(T) && !BOOST_HOF_IS_POLYMORPHIC(T)), 
0185     alias_inherit<T, Tag>, 
0186     alias<T, Tag>
0187 >
0188 {};
0189 
0190 #if BOOST_HOF_HAS_EBO
0191 template<class T, class Tag>
0192 struct alias_empty
0193 : std::conditional<(BOOST_HOF_IS_EMPTY(T)), 
0194     typename alias_try_inherit<T, Tag>::type, 
0195     alias<T, Tag>
0196 >
0197 {};
0198 #else
0199 template<class T, class Tag>
0200 struct alias_empty
0201 : std::conditional<
0202         BOOST_HOF_IS_EMPTY(T) && 
0203         BOOST_HOF_IS_LITERAL(T) && 
0204         BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(T),
0205     alias_static<T, Tag>,
0206     alias<T, Tag>
0207 >
0208 {};
0209 #endif
0210 
0211 }
0212 
0213 }} // namespace boost::hof
0214 
0215 #ifdef _MSC_VER
0216 #pragma warning(pop)
0217 #endif
0218 
0219 #endif