|
| 1 | +/*! |
| 2 | +@file |
| 3 | +Forward declares `boost::hana::basic_string`. |
| 4 | +
|
| 5 | +@copyright Louis Dionne 2013-2017 |
| 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_BASIC_STRING_HPP |
| 11 | +#define BOOST_HANA_FWD_BASIC_STRING_HPP |
| 12 | + |
| 13 | +#include <boost/hana/config.hpp> |
| 14 | +#include <boost/hana/fwd/core/make.hpp> |
| 15 | +#include <boost/hana/fwd/core/to.hpp> |
| 16 | + |
| 17 | + |
| 18 | +BOOST_HANA_NAMESPACE_BEGIN |
| 19 | +#ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 20 | + //! @ingroup group-datatypes |
| 21 | + //! Compile-time basic_string<Ch>. |
| 22 | + //! |
| 23 | + //! Conceptually, a `hana::string` is like a tuple holding |
| 24 | + //! `integral_constant`s of underlying type `char`. However, the |
| 25 | + //! interface of `hana::string` is not as rich as that of a tuple, |
| 26 | + //! because a string can only hold compile-time characters as opposed |
| 27 | + //! to any kind of object. |
| 28 | + //! |
| 29 | + //! Compile-time strings are used for simple purposes like being keys in a |
| 30 | + //! `hana::map` or tagging the members of a `Struct`. However, you might |
| 31 | + //! find that `hana::string` does not provide enough functionality to be |
| 32 | + //! used as a full-blown compile-time string implementation (e.g. regexp |
| 33 | + //! matching or substring finding). Indeed, providing a comprehensive |
| 34 | + //! string interface is a lot of job, and it is out of the scope of the |
| 35 | + //! library for the time being. |
| 36 | + //! |
| 37 | + //! |
| 38 | + //! @note |
| 39 | + //! The representation of `hana::basic_string` takes character type |
| 40 | + //! template parameters are `char`s. |
| 41 | + //! The proper way to access the contents of |
| 42 | + //! a `hana::string` as character constants is to use `hana::unpack`, |
| 43 | + //! `.c_str()` or `hana::to<ChT const*>`, as documented below. More |
| 44 | + //! details [in the tutorial](@ref tutorial-containers-types). |
| 45 | + //! |
| 46 | + //! |
| 47 | + //! Modeled concepts |
| 48 | + //! ---------------- |
| 49 | + //! For most purposes, a `hana::basic_string<ChT>` is functionally |
| 50 | + //! equivalent to a tuple holding `Constant`s of underlying type `ChT`. |
| 51 | + //! |
| 52 | + //! 1. `Comparable`\n |
| 53 | + //! Two strings are equal if and only if they have the same number of |
| 54 | + //! characters and characters at corresponding indices are equal. |
| 55 | + //! @include example/string/comparable.cpp |
| 56 | + //! |
| 57 | + //! 2. `Orderable`\n |
| 58 | + //! The total order implemented for `Orderable` is the usual |
| 59 | + //! lexicographical comparison of strings. |
| 60 | + //! @include example/string/orderable.cpp |
| 61 | + //! |
| 62 | + //! 3. `Monoid`\n |
| 63 | + //! Strings form a monoid under concatenation, with the neutral element |
| 64 | + //! being the empty string. |
| 65 | + //! @include example/string/monoid.cpp |
| 66 | + //! |
| 67 | + //! 4. `Foldable`\n |
| 68 | + //! Folding a string is equivalent to folding the sequence of its |
| 69 | + //! characters. |
| 70 | + //! @include example/string/foldable.cpp |
| 71 | + //! |
| 72 | + //! 5. `Iterable`\n |
| 73 | + //! Iterating over a string is equivalent to iterating over the sequence |
| 74 | + //! of its characters. Also note that `operator[]` can be used instead of |
| 75 | + //! the `at` function. |
| 76 | + //! @include example/string/iterable.cpp |
| 77 | + //! |
| 78 | + //! 6. `Searchable`\n |
| 79 | + //! Searching through a string is equivalent to searching through the |
| 80 | + //! sequence of its characters. |
| 81 | + //! @include example/string/searchable.cpp |
| 82 | + //! |
| 83 | + //! 7. `Hashable`\n |
| 84 | + //! The hash of a compile-time string is a type uniquely representing |
| 85 | + //! that string. |
| 86 | + //! @include example/string/hashable.cpp |
| 87 | + //! |
| 88 | + //! |
| 89 | + //! Conversion to `char const*` |
| 90 | + //! --------------------------- |
| 91 | + //! A `hana::string` can be converted to a `constexpr` null-delimited |
| 92 | + //! string of type `char const*` by using the `c_str()` method or |
| 93 | + //! `hana::to<char const*>`. This makes it easy to turn a compile-time |
| 94 | + //! string into a runtime string. However, note that this conversion is |
| 95 | + //! not an embedding, because `char const*` does not model the same |
| 96 | + //! concepts as `hana::string` does. |
| 97 | + //! @include example/string/to.cpp |
| 98 | + //! |
| 99 | + //! Conversion from any Constant holding a `char const*` |
| 100 | + //! ---------------------------------------------------- |
| 101 | + //! A `hana::string` can be created from any `Constant` whose underlying |
| 102 | + //! value is convertible to a `char const*` by using `hana::to`. The |
| 103 | + //! contents of the `char const*` are used to build the content of the |
| 104 | + //! `hana::string`. |
| 105 | + //! @include example/string/from_c_str.cpp |
| 106 | + //! |
| 107 | + //! Rationale for `hana::string` not being a `Constant` itself |
| 108 | + //! ---------------------------------------------------------- |
| 109 | + //! The underlying type held by a `hana::string` could be either `char const*` |
| 110 | + //! or some other constexpr-enabled string-like container. In the first case, |
| 111 | + //! `hana::string` can not be a `Constant` because the models of several |
| 112 | + //! concepts would not be respected by the underlying type, causing `value` |
| 113 | + //! not to be structure-preserving. Providing an underlying value of |
| 114 | + //! constexpr-enabled string-like container type like `std::string_view` |
| 115 | + //! would be great, but that's a bit complicated for the time being. |
| 116 | + template <typename Ch, Ch...> |
| 117 | + struct basic_string { |
| 118 | + // Default-construct a `hana::basic_string`; no-op since `hana::basic_string` is stateless. |
| 119 | + constexpr basic_string() = default; |
| 120 | + |
| 121 | + // Copy-construct a `hana::basic_string`; no-op since `hana::basic_string` is stateless. |
| 122 | + constexpr basic_string(basic_string const&) = default; |
| 123 | + |
| 124 | + //! Equivalent to `hana::equal` |
| 125 | + template <typename X, typename Y> |
| 126 | + friend constexpr auto operator==(X&& x, Y&& y); |
| 127 | + |
| 128 | + //! Equivalent to `hana::not_equal` |
| 129 | + template <typename X, typename Y> |
| 130 | + friend constexpr auto operator!=(X&& x, Y&& y); |
| 131 | + |
| 132 | + //! Equivalent to `hana::less` |
| 133 | + template <typename X, typename Y> |
| 134 | + friend constexpr auto operator<(X&& x, Y&& y); |
| 135 | + |
| 136 | + //! Equivalent to `hana::greater` |
| 137 | + template <typename X, typename Y> |
| 138 | + friend constexpr auto operator>(X&& x, Y&& y); |
| 139 | + |
| 140 | + //! Equivalent to `hana::less_equal` |
| 141 | + template <typename X, typename Y> |
| 142 | + friend constexpr auto operator<=(X&& x, Y&& y); |
| 143 | + |
| 144 | + //! Equivalent to `hana::greater_equal` |
| 145 | + template <typename X, typename Y> |
| 146 | + friend constexpr auto operator>=(X&& x, Y&& y); |
| 147 | + |
| 148 | + //! Performs concatenation; equivalent to `hana::plus` |
| 149 | + template <typename X, typename Y> |
| 150 | + friend constexpr auto operator+(X&& x, Y&& y); |
| 151 | + |
| 152 | + //! Equivalent to `hana::at` |
| 153 | + template <typename N> |
| 154 | + constexpr decltype(auto) operator[](N&& n); |
| 155 | + |
| 156 | + //! Returns a null-delimited C-style string. |
| 157 | + static constexpr Ch const* c_str(); |
| 158 | + }; |
| 159 | +#else |
| 160 | + template <typename CharT, CharT ...s> |
| 161 | + struct basic_string; |
| 162 | +#endif |
| 163 | + |
| 164 | + //! Tag representing a compile-time string. |
| 165 | + //! @relates hana::string |
| 166 | + template <typename CharT> |
| 167 | + struct basic_string_tag { }; |
| 168 | + |
| 169 | +#ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 170 | + //! Create a compile-time `hana::string` from a parameter pack of `char` |
| 171 | + //! `integral_constant`s. |
| 172 | + //! @relates hana::string |
| 173 | + //! |
| 174 | + //! Given zero or more `integral_constant`s of underlying type `char`, |
| 175 | + //! `make<string_tag>` creates a `hana::string` containing those characters. |
| 176 | + //! This is provided mostly for consistency with the rest of the library, |
| 177 | + //! as `hana::string_c` is more convenient to use in most cases. |
| 178 | + //! |
| 179 | + //! |
| 180 | + //! Example |
| 181 | + //! ------- |
| 182 | + //! @include example/string/make.cpp |
| 183 | + template <typename Ch> |
| 184 | + constexpr auto make<basic_string_tag<Ch>> = [](auto&& ...chars) { |
| 185 | + return basic_string<Ch>{}; |
| 186 | + }; |
| 187 | +#endif |
| 188 | + |
| 189 | + //! Alias to `make<string_tag>`; provided for convenience. |
| 190 | + //! @relates hana::string |
| 191 | + template <typename CharT> |
| 192 | + constexpr auto make_basic_string = make<basic_string_tag<CharT>>; |
| 193 | + |
| 194 | + //! Equivalent to `to<string_tag>`; provided for convenience. |
| 195 | + //! @relates hana::string |
| 196 | + template <typename CharT> |
| 197 | + constexpr auto to_basic_string = to<basic_string_tag<CharT>>; |
| 198 | + |
| 199 | + //! Create a compile-time string from a parameter pack of characters. |
| 200 | + //! @relates hana::string |
| 201 | + //! |
| 202 | + //! |
| 203 | + //! Example |
| 204 | + //! ------- |
| 205 | + //! @include example/string/string_c.cpp |
| 206 | +#ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 207 | + template <typename Ch, Ch ...s> |
| 208 | + constexpr basic_string<Ch, s...> basic_string_c{}; |
| 209 | +#else |
| 210 | + template <typename CharT, CharT ...s> |
| 211 | + constexpr basic_string<CharT, s...> basic_string_c{}; |
| 212 | +#endif |
| 213 | + |
| 214 | + //! Create a compile-time string from a string literal. |
| 215 | + //! @relates hana::basic_string |
| 216 | + //! |
| 217 | + //! This macro is a more convenient alternative to `basic_string_c` |
| 218 | + //! for creating compile-time strings. However, since this macro uses |
| 219 | + //! a lambda internally, it can't be used in an unevaluated context, |
| 220 | + //! or where a constant expression is expected before C++17. |
| 221 | + //! |
| 222 | + //! |
| 223 | + //! Example |
| 224 | + //! ------- |
| 225 | + //! @include example/basic_string/macro.cpp |
| 226 | +#ifdef BOOST_HANA_DOXYGEN_INVOKED |
| 227 | + auto BOOST_HANA_BASIC_STRING(type, s) = see documentation; |
| 228 | + #define BOOST_HANA_BASIC_STRING(type, s) see documentation |
| 229 | + |
| 230 | + // Note: |
| 231 | + // The trick above seems to exploit a bug in Doxygen, which makes the |
| 232 | + // BOOST_HANA_STRING macro appear in the related objects of hana::string |
| 233 | + // (as we want it to). |
| 234 | +#else |
| 235 | + // defined in <boost/hana/basic_string.hpp> |
| 236 | +#endif |
| 237 | + |
| 238 | +#ifdef BOOST_HANA_CONFIG_ENABLE_BASIC_STRING_UDL |
| 239 | + namespace literals { |
| 240 | + //! Creates a compile-time string from a string literal. |
| 241 | + //! @relatesalso boost::hana::string |
| 242 | + //! |
| 243 | + //! The string literal is parsed at compile-time and the result is |
| 244 | + //! returned as a `hana::string`. This feature is an extension that |
| 245 | + //! is disabled by default; see below for details. |
| 246 | + //! |
| 247 | + //! @note |
| 248 | + //! Only narrow string literals are supported right now; support for |
| 249 | + //! fancier types of string literals like wide or UTF-XX might be |
| 250 | + //! added in the future if there is a demand for it. See [this issue] |
| 251 | + //! [Hana.issue80] if you need this. |
| 252 | + //! |
| 253 | + //! @warning |
| 254 | + //! This user-defined literal is an extension which requires a special |
| 255 | + //! string literal operator that is not part of the standard yet. |
| 256 | + //! That operator is supported by both Clang and GCC, and several |
| 257 | + //! proposals were made for it to enter C++17. However, since it is |
| 258 | + //! not standard, it is disabled by default and defining the |
| 259 | + //! `BOOST_HANA_CONFIG_ENABLE_STRING_UDL` config macro is required |
| 260 | + //! to get this operator. Hence, if you want to stay safe, just use |
| 261 | + //! the `BOOST_HANA_STRING` macro instead. If you want to be fast and |
| 262 | + //! furious (I do), define `BOOST_HANA_CONFIG_ENABLE_STRING_UDL`. |
| 263 | + //! |
| 264 | + //! |
| 265 | + //! Example |
| 266 | + //! ------- |
| 267 | + //! @include example/string/literal.cpp |
| 268 | + //! |
| 269 | + //! [Hana.issue80]: https://github.com/boostorg/hana/issues/80 |
| 270 | + template <typename CharT, CharT ...s> |
| 271 | + constexpr auto operator"" _s(); |
| 272 | + } |
| 273 | +#endif |
| 274 | +BOOST_HANA_NAMESPACE_END |
| 275 | + |
| 276 | +#endif // !BOOST_HANA_FWD_BASIC_STRING_HPP |
0 commit comments