Skip to content

Commit 7a3e048

Browse files
committed
[string] Add a model of the Monoid concept
Fixes #117
1 parent 9fe9d2f commit 7a3e048

File tree

7 files changed

+127
-15
lines changed

7 files changed

+127
-15
lines changed

example/misc/printf.cpp

+3-9
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44

55
#include <boost/hana/adjust_if.hpp>
66
#include <boost/hana/at_key.hpp>
7-
#include <boost/hana/core/to.hpp>
87
#include <boost/hana/core/is_a.hpp>
8+
#include <boost/hana/core/to.hpp>
99
#include <boost/hana/filter.hpp>
10-
#include <boost/hana/fold_left.hpp>
1110
#include <boost/hana/functional/compose.hpp>
1211
#include <boost/hana/functional/partial.hpp>
1312
#include <boost/hana/map.hpp>
1413
#include <boost/hana/not.hpp>
1514
#include <boost/hana/pair.hpp>
1615
#include <boost/hana/prepend.hpp>
1716
#include <boost/hana/string.hpp>
17+
#include <boost/hana/sum.hpp>
1818
#include <boost/hana/tuple.hpp>
1919
#include <boost/hana/type.hpp>
2020
#include <boost/hana/unpack.hpp>
@@ -29,12 +29,6 @@ constexpr auto formats = hana::make_map(
2929
hana::make_pair(hana::type_c<char const*>, hana::string_c<'%', 's'>)
3030
);
3131

32-
struct concat_strings {
33-
template <char ...s1, char ...s2>
34-
constexpr auto operator()(hana::string<s1...>, hana::string<s2...>) const
35-
{ return hana::string_c<s1..., s2...>; }
36-
};
37-
3832
template <typename ...Tokens>
3933
constexpr auto format(Tokens ...tokens_) {
4034
auto tokens = hana::make_tuple(tokens_...);
@@ -50,7 +44,7 @@ constexpr auto format(Tokens ...tokens_) {
5044
hana::compose(hana::partial(hana::at_key, formats), hana::typeid_)
5145
);
5246

53-
auto format_string = hana::fold_left(format_string_tokens, hana::string_c<>, concat_strings{});
47+
auto format_string = hana::sum<hana::string_tag>(format_string_tokens);
5448
auto variables = hana::filter(tokens, hana::compose(hana::not_, hana::is_a<hana::string_tag>));
5549
return hana::prepend(variables, format_string);
5650
}

example/string/monoid.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright Louis Dionne 2013-2016
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4+
5+
#include <boost/hana/assert.hpp>
6+
#include <boost/hana/equal.hpp>
7+
#include <boost/hana/plus.hpp>
8+
#include <boost/hana/string.hpp>
9+
namespace hana = boost::hana;
10+
11+
12+
auto hello_world = BOOST_HANA_STRING("Hello ") + BOOST_HANA_STRING("world!");
13+
BOOST_HANA_CONSTANT_CHECK(hello_world == BOOST_HANA_STRING("Hello world!"));
14+
15+
int main() { }

include/boost/hana/fwd/string.hpp

+15-6
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ BOOST_HANA_NAMESPACE_BEGIN
3838
//! The representation of `hana::string` is implementation-defined.
3939
//! In particular, one should not take for granted that the template
4040
//! parameters are `char`s. The proper way to access the contents of
41-
//! a `hana::string` as character constants is to use `hana::unpack`
42-
//! or `hana::to<char const*>`, as documented below.
41+
//! a `hana::string` as character constants is to use `hana::unpack`,
42+
//! `.c_str()` or `hana::to<char const*>`, as documented below.
4343
//!
4444
//!
4545
//! Modeled concepts
@@ -57,23 +57,28 @@ BOOST_HANA_NAMESPACE_BEGIN
5757
//! lexicographical comparison of strings.
5858
//! @include example/string/orderable.cpp
5959
//!
60-
//! 3. `Foldable`\n
60+
//! 3. `Monoid`\n
61+
//! Strings form a monoid under concatenation, with the neutral element
62+
//! being the empty string.
63+
//! @include example/string/monoid.cpp
64+
//!
65+
//! 4. `Foldable`\n
6166
//! Folding a string is equivalent to folding the sequence of its
6267
//! characters.
6368
//! @include example/string/foldable.cpp
6469
//!
65-
//! 4. `Iterable`\n
70+
//! 5. `Iterable`\n
6671
//! Iterating over a string is equivalent to iterating over the sequence
6772
//! of its characters. Also note that `operator[]` can be used instead of
6873
//! the `at` function.
6974
//! @include example/string/iterable.cpp
7075
//!
71-
//! 5. `Searchable`\n
76+
//! 6. `Searchable`\n
7277
//! Searching through a string is equivalent to searching through the
7378
//! sequence of its characters.
7479
//! @include example/string/searchable.cpp
7580
//!
76-
//! 6. `Hashable`\n
81+
//! 7. `Hashable`\n
7782
//! The hash of a compile-time string is a type uniquely representing
7883
//! that string.
7984
//! @include example/string/hashable.cpp
@@ -125,6 +130,10 @@ BOOST_HANA_NAMESPACE_BEGIN
125130
template <typename X, typename Y>
126131
friend constexpr auto operator>=(X&& x, Y&& y);
127132

133+
//! Performs concatenation; equivalent to `hana::plus`
134+
template <typename X, typename Y>
135+
friend constexpr auto operator+(X&& x, Y&& y);
136+
128137
//! Equivalent to `hana::at`
129138
template <typename N>
130139
constexpr decltype(auto) operator[](N&& n);

include/boost/hana/string.hpp

+26
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ Distributed under the Boost Software License, Version 1.0.
3232
#include <boost/hana/fwd/is_empty.hpp>
3333
#include <boost/hana/fwd/length.hpp>
3434
#include <boost/hana/fwd/less.hpp>
35+
#include <boost/hana/fwd/plus.hpp>
3536
#include <boost/hana/fwd/unpack.hpp>
37+
#include <boost/hana/fwd/zero.hpp>
3638
#include <boost/hana/if.hpp>
3739
#include <boost/hana/integral_constant.hpp>
3840
#include <boost/hana/optional.hpp>
@@ -177,6 +179,30 @@ BOOST_HANA_NAMESPACE_BEGIN
177179
}
178180
};
179181

182+
//////////////////////////////////////////////////////////////////////////
183+
// Monoid
184+
//////////////////////////////////////////////////////////////////////////
185+
template <>
186+
struct plus_impl<string_tag, string_tag> {
187+
template <char ...s1, char ...s2>
188+
static constexpr auto
189+
apply(string<s1...> const&, string<s2...> const&) {
190+
return string<s1..., s2...>{};
191+
}
192+
};
193+
194+
template <>
195+
struct zero_impl<string_tag> {
196+
static constexpr auto apply() {
197+
return string<>{};
198+
}
199+
};
200+
201+
template <char ...s1, char ...s2>
202+
constexpr auto operator+(string<s1...> const&, string<s2...> const&) {
203+
return hana::string<s1..., s2...>{};
204+
}
205+
180206
//////////////////////////////////////////////////////////////////////////
181207
// Foldable
182208
//////////////////////////////////////////////////////////////////////////

test/string/laws.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <laws/foldable.hpp>
1010
#include <laws/hashable.hpp>
1111
#include <laws/iterable.hpp>
12+
#include <laws/monoid.hpp>
1213
#include <laws/orderable.hpp>
1314
#include <laws/searchable.hpp>
1415
namespace hana = boost::hana;
@@ -31,6 +32,21 @@ int main() {
3132
hana::test::TestHashable<hana::string_tag>{strings};
3233
}
3334

35+
// Monoid
36+
{
37+
auto strings = hana::make_tuple(
38+
BOOST_HANA_STRING(""),
39+
BOOST_HANA_STRING("a"),
40+
BOOST_HANA_STRING("ab"),
41+
BOOST_HANA_STRING("abc"),
42+
BOOST_HANA_STRING("abcd"),
43+
BOOST_HANA_STRING("abcde"),
44+
BOOST_HANA_STRING("ba")
45+
);
46+
47+
hana::test::TestMonoid<hana::string_tag>{strings};
48+
}
49+
3450
// Foldable and Iterable
3551
{
3652
auto strings = hana::make_tuple(

test/string/plus.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright Louis Dionne 2013-2016
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4+
5+
#include <boost/hana/assert.hpp>
6+
#include <boost/hana/equal.hpp>
7+
#include <boost/hana/plus.hpp>
8+
#include <boost/hana/string.hpp>
9+
namespace hana = boost::hana;
10+
11+
12+
int main() {
13+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
14+
hana::plus(BOOST_HANA_STRING(""), BOOST_HANA_STRING("")),
15+
BOOST_HANA_STRING("")
16+
));
17+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
18+
hana::plus(BOOST_HANA_STRING("abcd"), BOOST_HANA_STRING("")),
19+
BOOST_HANA_STRING("abcd")
20+
));
21+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
22+
hana::plus(BOOST_HANA_STRING(""), BOOST_HANA_STRING("abcd")),
23+
BOOST_HANA_STRING("abcd")
24+
));
25+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
26+
hana::plus(BOOST_HANA_STRING("abcd"), BOOST_HANA_STRING("efg")),
27+
BOOST_HANA_STRING("abcdefg")
28+
));
29+
30+
// check operator
31+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
32+
BOOST_HANA_STRING("abc") + BOOST_HANA_STRING("def"),
33+
BOOST_HANA_STRING("abcdef")
34+
));
35+
}

test/string/zero.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright Louis Dionne 2013-2016
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4+
5+
#include <boost/hana/assert.hpp>
6+
#include <boost/hana/equal.hpp>
7+
#include <boost/hana/string.hpp>
8+
#include <boost/hana/zero.hpp>
9+
namespace hana = boost::hana;
10+
11+
12+
int main() {
13+
BOOST_HANA_CONSTANT_CHECK(hana::equal(
14+
hana::zero<hana::string_tag>(),
15+
BOOST_HANA_STRING("")
16+
));
17+
}

0 commit comments

Comments
 (0)