Skip to content

Commit

Permalink
[string] Add a model of the Monoid concept
Browse files Browse the repository at this point in the history
Fixes #117
  • Loading branch information
ldionne committed Nov 17, 2016
1 parent 9fe9d2f commit 7a3e048
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 15 deletions.
12 changes: 3 additions & 9 deletions example/misc/printf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@

#include <boost/hana/adjust_if.hpp>
#include <boost/hana/at_key.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/core/is_a.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/filter.hpp>
#include <boost/hana/fold_left.hpp>
#include <boost/hana/functional/compose.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/map.hpp>
#include <boost/hana/not.hpp>
#include <boost/hana/pair.hpp>
#include <boost/hana/prepend.hpp>
#include <boost/hana/string.hpp>
#include <boost/hana/sum.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>
#include <boost/hana/unpack.hpp>
Expand All @@ -29,12 +29,6 @@ constexpr auto formats = hana::make_map(
hana::make_pair(hana::type_c<char const*>, hana::string_c<'%', 's'>)
);

struct concat_strings {
template <char ...s1, char ...s2>
constexpr auto operator()(hana::string<s1...>, hana::string<s2...>) const
{ return hana::string_c<s1..., s2...>; }
};

template <typename ...Tokens>
constexpr auto format(Tokens ...tokens_) {
auto tokens = hana::make_tuple(tokens_...);
Expand All @@ -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<hana::string_tag>(format_string_tokens);
auto variables = hana::filter(tokens, hana::compose(hana::not_, hana::is_a<hana::string_tag>));
return hana::prepend(variables, format_string);
}
Expand Down
15 changes: 15 additions & 0 deletions example/string/monoid.cpp
Original file line number Diff line number Diff line change
@@ -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 <boost/hana/assert.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/plus.hpp>
#include <boost/hana/string.hpp>
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() { }
21 changes: 15 additions & 6 deletions include/boost/hana/fwd/string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<char const*>`, as documented below.
//! a `hana::string` as character constants is to use `hana::unpack`,
//! `.c_str()` or `hana::to<char const*>`, as documented below.
//!
//!
//! Modeled concepts
Expand All @@ -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
Expand Down Expand Up @@ -125,6 +130,10 @@ BOOST_HANA_NAMESPACE_BEGIN
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);
Expand Down
26 changes: 26 additions & 0 deletions include/boost/hana/string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/length.hpp>
#include <boost/hana/fwd/less.hpp>
#include <boost/hana/fwd/plus.hpp>
#include <boost/hana/fwd/unpack.hpp>
#include <boost/hana/fwd/zero.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/optional.hpp>
Expand Down Expand Up @@ -177,6 +179,30 @@ BOOST_HANA_NAMESPACE_BEGIN
}
};

//////////////////////////////////////////////////////////////////////////
// Monoid
//////////////////////////////////////////////////////////////////////////
template <>
struct plus_impl<string_tag, string_tag> {
template <char ...s1, char ...s2>
static constexpr auto
apply(string<s1...> const&, string<s2...> const&) {
return string<s1..., s2...>{};
}
};

template <>
struct zero_impl<string_tag> {
static constexpr auto apply() {
return string<>{};
}
};

template <char ...s1, char ...s2>
constexpr auto operator+(string<s1...> const&, string<s2...> const&) {
return hana::string<s1..., s2...>{};
}

//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
Expand Down
16 changes: 16 additions & 0 deletions test/string/laws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <laws/foldable.hpp>
#include <laws/hashable.hpp>
#include <laws/iterable.hpp>
#include <laws/monoid.hpp>
#include <laws/orderable.hpp>
#include <laws/searchable.hpp>
namespace hana = boost::hana;
Expand All @@ -31,6 +32,21 @@ int main() {
hana::test::TestHashable<hana::string_tag>{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<hana::string_tag>{strings};
}

// Foldable and Iterable
{
auto strings = hana::make_tuple(
Expand Down
35 changes: 35 additions & 0 deletions test/string/plus.cpp
Original file line number Diff line number Diff line change
@@ -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 <boost/hana/assert.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/plus.hpp>
#include <boost/hana/string.hpp>
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")
));
}
17 changes: 17 additions & 0 deletions test/string/zero.cpp
Original file line number Diff line number Diff line change
@@ -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 <boost/hana/assert.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/string.hpp>
#include <boost/hana/zero.hpp>
namespace hana = boost::hana;


int main() {
BOOST_HANA_CONSTANT_CHECK(hana::equal(
hana::zero<hana::string_tag>(),
BOOST_HANA_STRING("")
));
}

1 comment on commit 7a3e048

@ricejasonf
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Please sign in to comment.