diff --git a/example/misc/printf.cpp b/example/misc/printf.cpp index 45bd49a08c..791ec49ecd 100644 --- a/example/misc/printf.cpp +++ b/example/misc/printf.cpp @@ -4,10 +4,9 @@ #include #include -#include #include +#include #include -#include #include #include #include @@ -15,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -29,12 +29,6 @@ constexpr auto formats = hana::make_map( hana::make_pair(hana::type_c, hana::string_c<'%', 's'>) ); -struct concat_strings { - template - constexpr auto operator()(hana::string, hana::string) const - { return hana::string_c; } -}; - template constexpr auto format(Tokens ...tokens_) { auto tokens = hana::make_tuple(tokens_...); @@ -50,7 +44,7 @@ constexpr auto format(Tokens ...tokens_) { hana::compose(hana::partial(hana::at_key, formats), hana::typeid_) ); - auto format_string = hana::fold_left(format_string_tokens, hana::string_c<>, concat_strings{}); + auto format_string = hana::sum(format_string_tokens); auto variables = hana::filter(tokens, hana::compose(hana::not_, hana::is_a)); return hana::prepend(variables, format_string); } diff --git a/example/string/monoid.cpp b/example/string/monoid.cpp new file mode 100644 index 0000000000..5774640a19 --- /dev/null +++ b/example/string/monoid.cpp @@ -0,0 +1,15 @@ +// Copyright Louis Dionne 2013-2016 +// 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 +#include +#include +#include +namespace hana = boost::hana; + + +auto hello_world = BOOST_HANA_STRING("Hello ") + BOOST_HANA_STRING("world!"); +BOOST_HANA_CONSTANT_CHECK(hello_world == BOOST_HANA_STRING("Hello world!")); + +int main() { } diff --git a/include/boost/hana/fwd/string.hpp b/include/boost/hana/fwd/string.hpp index d6d36a104f..c3476d7e72 100644 --- a/include/boost/hana/fwd/string.hpp +++ b/include/boost/hana/fwd/string.hpp @@ -38,8 +38,8 @@ BOOST_HANA_NAMESPACE_BEGIN //! The representation of `hana::string` is implementation-defined. //! In particular, one should not take for granted that the template //! parameters are `char`s. The proper way to access the contents of - //! a `hana::string` as character constants is to use `hana::unpack` - //! or `hana::to`, as documented below. + //! a `hana::string` as character constants is to use `hana::unpack`, + //! `.c_str()` or `hana::to`, as documented below. //! //! //! Modeled concepts @@ -57,23 +57,28 @@ BOOST_HANA_NAMESPACE_BEGIN //! lexicographical comparison of strings. //! @include example/string/orderable.cpp //! - //! 3. `Foldable`\n + //! 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 //! - //! 4. `Iterable`\n + //! 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 //! - //! 5. `Searchable`\n + //! 6. `Searchable`\n //! Searching through a string is equivalent to searching through the //! sequence of its characters. //! @include example/string/searchable.cpp //! - //! 6. `Hashable`\n + //! 7. `Hashable`\n //! The hash of a compile-time string is a type uniquely representing //! that string. //! @include example/string/hashable.cpp @@ -125,6 +130,10 @@ BOOST_HANA_NAMESPACE_BEGIN template friend constexpr auto operator>=(X&& x, Y&& y); + //! Performs concatenation; equivalent to `hana::plus` + template + friend constexpr auto operator+(X&& x, Y&& y); + //! Equivalent to `hana::at` template constexpr decltype(auto) operator[](N&& n); diff --git a/include/boost/hana/string.hpp b/include/boost/hana/string.hpp index 8764bc85be..a1b97d2cbb 100644 --- a/include/boost/hana/string.hpp +++ b/include/boost/hana/string.hpp @@ -32,7 +32,9 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include +#include #include +#include #include #include #include @@ -177,6 +179,30 @@ BOOST_HANA_NAMESPACE_BEGIN } }; + ////////////////////////////////////////////////////////////////////////// + // Monoid + ////////////////////////////////////////////////////////////////////////// + template <> + struct plus_impl { + template + static constexpr auto + apply(string const&, string const&) { + return string{}; + } + }; + + template <> + struct zero_impl { + static constexpr auto apply() { + return string<>{}; + } + }; + + template + constexpr auto operator+(string const&, string const&) { + return hana::string{}; + } + ////////////////////////////////////////////////////////////////////////// // Foldable ////////////////////////////////////////////////////////////////////////// diff --git a/test/string/laws.cpp b/test/string/laws.cpp index 2b83b1f0a0..10d77fe51f 100644 --- a/test/string/laws.cpp +++ b/test/string/laws.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include namespace hana = boost::hana; @@ -31,6 +32,21 @@ int main() { hana::test::TestHashable{strings}; } + // Monoid + { + auto strings = hana::make_tuple( + BOOST_HANA_STRING(""), + BOOST_HANA_STRING("a"), + BOOST_HANA_STRING("ab"), + BOOST_HANA_STRING("abc"), + BOOST_HANA_STRING("abcd"), + BOOST_HANA_STRING("abcde"), + BOOST_HANA_STRING("ba") + ); + + hana::test::TestMonoid{strings}; + } + // Foldable and Iterable { auto strings = hana::make_tuple( diff --git a/test/string/plus.cpp b/test/string/plus.cpp new file mode 100644 index 0000000000..54f3d2a935 --- /dev/null +++ b/test/string/plus.cpp @@ -0,0 +1,35 @@ +// Copyright Louis Dionne 2013-2016 +// 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 +#include +#include +#include +namespace hana = boost::hana; + + +int main() { + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::plus(BOOST_HANA_STRING(""), BOOST_HANA_STRING("")), + BOOST_HANA_STRING("") + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::plus(BOOST_HANA_STRING("abcd"), BOOST_HANA_STRING("")), + BOOST_HANA_STRING("abcd") + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::plus(BOOST_HANA_STRING(""), BOOST_HANA_STRING("abcd")), + BOOST_HANA_STRING("abcd") + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::plus(BOOST_HANA_STRING("abcd"), BOOST_HANA_STRING("efg")), + BOOST_HANA_STRING("abcdefg") + )); + + // check operator + BOOST_HANA_CONSTANT_CHECK(hana::equal( + BOOST_HANA_STRING("abc") + BOOST_HANA_STRING("def"), + BOOST_HANA_STRING("abcdef") + )); +} diff --git a/test/string/zero.cpp b/test/string/zero.cpp new file mode 100644 index 0000000000..64eaf3381e --- /dev/null +++ b/test/string/zero.cpp @@ -0,0 +1,17 @@ +// Copyright Louis Dionne 2013-2016 +// 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 +#include +#include +#include +namespace hana = boost::hana; + + +int main() { + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::zero(), + BOOST_HANA_STRING("") + )); +}