Skip to content

Commit

Permalink
[basic_string] Added basic_string, wstring
Browse files Browse the repository at this point in the history
    - Added classes basic_string and wstring.
    - Added macros BOOST_HANA_BASIC_STRING and BOOST_HANA_AUTO_STRING
    - Added user defined literal _s for basic_string if
          BOOST_HANA_CONFIG_ENABLE_BASIC_STRING_UDL directive is defined.
    - Added following integral_constant type aliases.
	  wchar_, char16_, char32_, basic_char
    - Added following integral_constant constants.
          wchar_c, char16_c, char32_c, basic_char_c
    - Added unit test codes for basic_string and wstring.
  • Loading branch information
yamasdais committed Mar 11, 2019
1 parent 4536973 commit 486d0d5
Show file tree
Hide file tree
Showing 58 changed files with 3,532 additions and 0 deletions.
404 changes: 404 additions & 0 deletions include/boost/hana/basic_string.hpp

Large diffs are not rendered by default.

276 changes: 276 additions & 0 deletions include/boost/hana/fwd/basic_string.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
/*!
@file
Forward declares `boost::hana::basic_string`.
@copyright Louis Dionne 2013-2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/

#ifndef BOOST_HANA_FWD_BASIC_STRING_HPP
#define BOOST_HANA_FWD_BASIC_STRING_HPP

#include <boost/hana/config.hpp>
#include <boost/hana/fwd/core/make.hpp>
#include <boost/hana/fwd/core/to.hpp>


BOOST_HANA_NAMESPACE_BEGIN
#ifdef BOOST_HANA_DOXYGEN_INVOKED
//! @ingroup group-datatypes
//! Compile-time basic_string<Ch>.
//!
//! Conceptually, a `hana::string` is like a tuple holding
//! `integral_constant`s of underlying type `char`. However, the
//! interface of `hana::string` is not as rich as that of a tuple,
//! because a string can only hold compile-time characters as opposed
//! to any kind of object.
//!
//! Compile-time strings are used for simple purposes like being keys in a
//! `hana::map` or tagging the members of a `Struct`. However, you might
//! find that `hana::string` does not provide enough functionality to be
//! used as a full-blown compile-time string implementation (e.g. regexp
//! matching or substring finding). Indeed, providing a comprehensive
//! string interface is a lot of job, and it is out of the scope of the
//! library for the time being.
//!
//!
//! @note
//! The representation of `hana::basic_string` takes character type
//! template parameters are `char`s.
//! The proper way to access the contents of
//! a `hana::string` as character constants is to use `hana::unpack`,
//! `.c_str()` or `hana::to<ChT const*>`, as documented below. More
//! details [in the tutorial](@ref tutorial-containers-types).
//!
//!
//! Modeled concepts
//! ----------------
//! For most purposes, a `hana::basic_string<ChT>` is functionally
//! equivalent to a tuple holding `Constant`s of underlying type `ChT`.
//!
//! 1. `Comparable`\n
//! Two strings are equal if and only if they have the same number of
//! characters and characters at corresponding indices are equal.
//! @include example/string/comparable.cpp
//!
//! 2. `Orderable`\n
//! The total order implemented for `Orderable` is the usual
//! lexicographical comparison of strings.
//! @include example/string/orderable.cpp
//!
//! 3. `Monoid`\n
//! Strings form a monoid under concatenation, with the neutral element
//! being the empty string.
//! @include example/string/monoid.cpp
//!
//! 4. `Foldable`\n
//! Folding a string is equivalent to folding the sequence of its
//! characters.
//! @include example/string/foldable.cpp
//!
//! 5. `Iterable`\n
//! Iterating over a string is equivalent to iterating over the sequence
//! of its characters. Also note that `operator[]` can be used instead of
//! the `at` function.
//! @include example/string/iterable.cpp
//!
//! 6. `Searchable`\n
//! Searching through a string is equivalent to searching through the
//! sequence of its characters.
//! @include example/string/searchable.cpp
//!
//! 7. `Hashable`\n
//! The hash of a compile-time string is a type uniquely representing
//! that string.
//! @include example/string/hashable.cpp
//!
//!
//! Conversion to `char const*`
//! ---------------------------
//! A `hana::string` can be converted to a `constexpr` null-delimited
//! string of type `char const*` by using the `c_str()` method or
//! `hana::to<char const*>`. This makes it easy to turn a compile-time
//! string into a runtime string. However, note that this conversion is
//! not an embedding, because `char const*` does not model the same
//! concepts as `hana::string` does.
//! @include example/string/to.cpp
//!
//! Conversion from any Constant holding a `char const*`
//! ----------------------------------------------------
//! A `hana::string` can be created from any `Constant` whose underlying
//! value is convertible to a `char const*` by using `hana::to`. The
//! contents of the `char const*` are used to build the content of the
//! `hana::string`.
//! @include example/string/from_c_str.cpp
//!
//! Rationale for `hana::string` not being a `Constant` itself
//! ----------------------------------------------------------
//! The underlying type held by a `hana::string` could be either `char const*`
//! or some other constexpr-enabled string-like container. In the first case,
//! `hana::string` can not be a `Constant` because the models of several
//! concepts would not be respected by the underlying type, causing `value`
//! not to be structure-preserving. Providing an underlying value of
//! constexpr-enabled string-like container type like `std::string_view`
//! would be great, but that's a bit complicated for the time being.
template <typename Ch, Ch...>
struct basic_string {
// Default-construct a `hana::basic_string`; no-op since `hana::basic_string` is stateless.
constexpr basic_string() = default;

// Copy-construct a `hana::basic_string`; no-op since `hana::basic_string` is stateless.
constexpr basic_string(basic_string const&) = default;

//! Equivalent to `hana::equal`
template <typename X, typename Y>
friend constexpr auto operator==(X&& x, Y&& y);

//! Equivalent to `hana::not_equal`
template <typename X, typename Y>
friend constexpr auto operator!=(X&& x, Y&& y);

//! Equivalent to `hana::less`
template <typename X, typename Y>
friend constexpr auto operator<(X&& x, Y&& y);

//! Equivalent to `hana::greater`
template <typename X, typename Y>
friend constexpr auto operator>(X&& x, Y&& y);

//! Equivalent to `hana::less_equal`
template <typename X, typename Y>
friend constexpr auto operator<=(X&& x, Y&& y);

//! Equivalent to `hana::greater_equal`
template <typename X, typename Y>
friend constexpr auto operator>=(X&& x, Y&& y);

//! Performs concatenation; equivalent to `hana::plus`
template <typename X, typename Y>
friend constexpr auto operator+(X&& x, Y&& y);

//! Equivalent to `hana::at`
template <typename N>
constexpr decltype(auto) operator[](N&& n);

//! Returns a null-delimited C-style string.
static constexpr Ch const* c_str();
};
#else
template <typename CharT, CharT ...s>
struct basic_string;
#endif

//! Tag representing a compile-time string.
//! @relates hana::string
template <typename CharT>
struct basic_string_tag { };

#ifdef BOOST_HANA_DOXYGEN_INVOKED
//! Create a compile-time `hana::string` from a parameter pack of `char`
//! `integral_constant`s.
//! @relates hana::string
//!
//! Given zero or more `integral_constant`s of underlying type `char`,
//! `make<string_tag>` creates a `hana::string` containing those characters.
//! This is provided mostly for consistency with the rest of the library,
//! as `hana::string_c` is more convenient to use in most cases.
//!
//!
//! Example
//! -------
//! @include example/string/make.cpp
template <typename Ch>
constexpr auto make<basic_string_tag<Ch>> = [](auto&& ...chars) {
return basic_string<Ch>{};
};
#endif

//! Alias to `make<string_tag>`; provided for convenience.
//! @relates hana::string
template <typename CharT>
constexpr auto make_basic_string = make<basic_string_tag<CharT>>;

//! Equivalent to `to<string_tag>`; provided for convenience.
//! @relates hana::string
template <typename CharT>
constexpr auto to_basic_string = to<basic_string_tag<CharT>>;

//! Create a compile-time string from a parameter pack of characters.
//! @relates hana::string
//!
//!
//! Example
//! -------
//! @include example/string/string_c.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <typename Ch, Ch ...s>
constexpr basic_string<Ch, s...> basic_string_c{};
#else
template <typename CharT, CharT ...s>
constexpr basic_string<CharT, s...> basic_string_c{};
#endif

//! Create a compile-time string from a string literal.
//! @relates hana::basic_string
//!
//! This macro is a more convenient alternative to `basic_string_c`
//! for creating compile-time strings. However, since this macro uses
//! a lambda internally, it can't be used in an unevaluated context,
//! or where a constant expression is expected before C++17.
//!
//!
//! Example
//! -------
//! @include example/basic_string/macro.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
auto BOOST_HANA_BASIC_STRING(type, s) = see documentation;
#define BOOST_HANA_BASIC_STRING(type, s) see documentation

// Note:
// The trick above seems to exploit a bug in Doxygen, which makes the
// BOOST_HANA_STRING macro appear in the related objects of hana::string
// (as we want it to).
#else
// defined in <boost/hana/basic_string.hpp>
#endif

#ifdef BOOST_HANA_CONFIG_ENABLE_BASIC_STRING_UDL
namespace literals {
//! Creates a compile-time string from a string literal.
//! @relatesalso boost::hana::string
//!
//! The string literal is parsed at compile-time and the result is
//! returned as a `hana::string`. This feature is an extension that
//! is disabled by default; see below for details.
//!
//! @note
//! Only narrow string literals are supported right now; support for
//! fancier types of string literals like wide or UTF-XX might be
//! added in the future if there is a demand for it. See [this issue]
//! [Hana.issue80] if you need this.
//!
//! @warning
//! This user-defined literal is an extension which requires a special
//! string literal operator that is not part of the standard yet.
//! That operator is supported by both Clang and GCC, and several
//! proposals were made for it to enter C++17. However, since it is
//! not standard, it is disabled by default and defining the
//! `BOOST_HANA_CONFIG_ENABLE_STRING_UDL` config macro is required
//! to get this operator. Hence, if you want to stay safe, just use
//! the `BOOST_HANA_STRING` macro instead. If you want to be fast and
//! furious (I do), define `BOOST_HANA_CONFIG_ENABLE_STRING_UDL`.
//!
//!
//! Example
//! -------
//! @include example/string/literal.cpp
//!
//! [Hana.issue80]: https://github.com/boostorg/hana/issues/80
template <typename CharT, CharT ...s>
constexpr auto operator"" _s();
}
#endif
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_FWD_BASIC_STRING_HPP
36 changes: 36 additions & 0 deletions include/boost/hana/fwd/integral_constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,42 @@ BOOST_HANA_NAMESPACE_BEGIN
constexpr char_<c> char_c{};


//! @relates hana::integral_constant
template <wchar_t c>
using wchar_ = integral_constant<wchar_t, c>;

//! @relates hana::integral_constant
template <wchar_t c>
constexpr wchar_<c> wchar_c{};


//! @relates hana::integral_constant
template <char16_t c>
using char16_ = integral_constant<char16_t, c>;

//! @relates hana::integral_constant
template <char16_t c>
constexpr char16_<c> char16_c{};


//! @relates hana::integral_constant
template <char32_t c>
using char32_ = integral_constant<char32_t, c>;

//! @relates hana::integral_constant
template <char32_t c>
constexpr char32_<c> char32_c{};


//! @relates hana::integral_constant
template <typename CharT, CharT c>
using basic_char_ = integral_constant<CharT, c>;

//! @relates hana::integral_constant
template <typename CharT, CharT c>
constexpr basic_char_<CharT, c> basic_char_c{};


//! @relates hana::integral_constant
template <short i>
using short_ = integral_constant<short, i>;
Expand Down
33 changes: 33 additions & 0 deletions include/boost/hana/wstring.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::wstring`.
@copyright Louis Dionne 2013-2018
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/

#ifndef BOOST_HANA_WSTRING_HPP
#define BOOST_HANA_WSTRING_HPP

#include <boost/hana/basic_string.hpp>
#include <boost/hana/fwd/core/make.hpp>
#include <boost/hana/fwd/core/to.hpp>

BOOST_HANA_NAMESPACE_BEGIN

template <wchar_t ...s>
using wstring = basic_string<wchar_t, s...>;

using wstring_tag = basic_string_tag<wchar_t>;

constexpr auto make_wstring = make<wstring_tag>;

constexpr auto to_wstring = to<wstring_tag>;

template <wchar_t ...s>
constexpr wstring<s...> wstring_c{};

BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_WSTRING_HPP
43 changes: 43 additions & 0 deletions test/basic_string/any_of.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#include <boost/hana/any_of.hpp>
#include <boost/hana/assert.hpp>
#include <boost/hana/basic_string.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/not.hpp>

#include "test_basic_string.hpp"
namespace hana = boost::hana;

template <typename C>
void test() {
BOOST_HANA_CONSTANT_CHECK(hana::any_of(
BOOST_HANA_BASIC_STRING(C, "abcd"),
hana::equal.to(hana::basic_char_c<C, CONVERT_C('b')>)
));

BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
BOOST_HANA_BASIC_STRING(C, ""),
hana::always(hana::true_c)
)));

BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
BOOST_HANA_BASIC_STRING(C, "abcd"),
hana::equal.to(hana::basic_char_c<C, CONVERT_C('z')>)
)));

BOOST_HANA_CONSTANT_CHECK(hana::any_of(
BOOST_HANA_BASIC_STRING(C, "abc\x80" "d"),
hana::equal.to(hana::basic_char_c<C, CONVERT_C('\x80')>)
));
}

int main() {
test<char>();
test<wchar_t>();
test<char16_t>();
test<char32_t>();
}
Loading

0 comments on commit 486d0d5

Please sign in to comment.