diff --git a/example/string/foldable.cpp b/example/string/foldable.cpp new file mode 100644 index 000000000..84df6b64e --- /dev/null +++ b/example/string/foldable.cpp @@ -0,0 +1,26 @@ +/* +@copyright Louis Dionne 2014 +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 +using namespace boost::hana; + + +int main() { + //! [main] + auto sum_string = [](auto str) { + return foldl(str, int_<0>, [](auto sum, auto c) { + constexpr int i = value(c) - 48; // convert character to decimal + return sum + int_; + }); + }; + + BOOST_HANA_CONSTANT_ASSERT( + sum_string(BOOST_HANA_STRING("1234")) == int_<1 + 2 + 3 + 4> + ); + //! [main] +} diff --git a/example/string/orderable.cpp b/example/string/orderable.cpp new file mode 100644 index 000000000..42b21eccb --- /dev/null +++ b/example/string/orderable.cpp @@ -0,0 +1,22 @@ +/* +@copyright Louis Dionne 2014 +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 +using namespace boost::hana; + + +int main() { + //! [main] + BOOST_HANA_CONSTANT_ASSERT( + BOOST_HANA_STRING("abc") < BOOST_HANA_STRING("bcd") + ); + + BOOST_HANA_CONSTANT_ASSERT( + BOOST_HANA_STRING("abcd") > BOOST_HANA_STRING("abc") + ); + //! [main] +} diff --git a/include/boost/hana/string.hpp b/include/boost/hana/string.hpp index 17ffece16..a412fea53 100644 --- a/include/boost/hana/string.hpp +++ b/include/boost/hana/string.hpp @@ -15,5 +15,7 @@ Distributed under the Boost Software License, Version 1.0. // Instances #include #include +#include +#include #endif // !BOOST_HANA_STRING_HPP diff --git a/include/boost/hana/string/comparable.hpp b/include/boost/hana/string/comparable.hpp index 874648221..d8f2c3655 100644 --- a/include/boost/hana/string/comparable.hpp +++ b/include/boost/hana/string/comparable.hpp @@ -25,18 +25,20 @@ namespace boost { namespace hana { //! @snippet example/string/comparable.cpp main template <> struct Comparable::instance : Comparable::equal_mcd { - static constexpr bool str_equal_impl(char const* s1, char const* s2) { + private: + static constexpr bool strequal(char const* s1, char const* s2) { while (*s1 != '\0' && *s2 != '\0') if (*s1++ != *s2++) return false; return *s1 == '\0' && *s2 == '\0'; } + public: template static constexpr auto equal_impl(S1 const&, S2 const&) { constexpr char const* s1 = S1::get(); constexpr char const* s2 = S2::get(); - return bool_; + return bool_; } }; }} // end namespace boost::hana diff --git a/include/boost/hana/string/foldable.hpp b/include/boost/hana/string/foldable.hpp new file mode 100644 index 000000000..08c5b4030 --- /dev/null +++ b/include/boost/hana/string/foldable.hpp @@ -0,0 +1,63 @@ +/*! +@file +Defines the instance of `boost::hana::Foldable` for `boost::hana::String`s. + +@copyright Louis Dionne 2014 +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_STRING_FOLDABLE_HPP +#define BOOST_HANA_STRING_FOLDABLE_HPP + +#include +#include +#include +#include +#include // for char_, size_t +#include + + +namespace boost { namespace hana { + //! Instance of `Foldable` for `String`s. + //! + //! For the purpose of being folded, `String`s are basically equivalent to + //! a tuple in which `IntegralConstant`s of underlying type `char` are + //! stored. + //! + //! ### Example + //! @snippet example/string/foldable.cpp main + template <> + struct Foldable::instance : Foldable::unpack_mcd { + private: + static constexpr detail::std::size_t strlen(char const* s) { + detail::std::size_t l = 0; + while (*s++ != '\0') + ++l; + return l; + } + + template + static constexpr decltype(auto) unpack_helper(S, F&& f, + detail::std::index_sequence) + { + constexpr char const* s = S::get(); + return detail::std::forward(f)(char_...); + } + + public: + template + static constexpr decltype(auto) unpack_impl(S s, F&& f) { + return unpack_helper(s, detail::std::forward(f), + detail::std::make_index_sequence{} + ); + } + + template + static constexpr auto length_impl(S) { + return size_t; + } + }; +}} // end namespace boost::hana + +#endif // !BOOST_HANA_STRING_FOLDABLE_HPP diff --git a/include/boost/hana/string/orderable.hpp b/include/boost/hana/string/orderable.hpp new file mode 100644 index 000000000..a41bd0502 --- /dev/null +++ b/include/boost/hana/string/orderable.hpp @@ -0,0 +1,47 @@ +/*! +@file +Defines the instance of `boost::hana::Orderable` for `boost::hana::String`s. + +@copyright Louis Dionne 2014 +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_STRING_ORDERABLE_HPP +#define BOOST_HANA_STRING_ORDERABLE_HPP + +#include +#include +#include + + +namespace boost { namespace hana { + //! Instance of `Orderable` for `String`s. + //! + //! The strict weak ordering implemented for `Orderable` is the usual + //! lexicographical comparison. + //! + //! ### Example + //! @snippet example/string/orderable.cpp main + template <> + struct Orderable::instance : Orderable::less_mcd { + private: + static constexpr bool strless(char const* s1, char const* s2) { + while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) + ++s1, ++s2; + + return (*s1 == '\0' && *s2 != '\0') || // s1 is shorter than s2 + (*s1 != '\0' && *s2 != '\0' && *s1 < *s2); // s1[0] < s2[0] + } + + public: + template + static constexpr auto less_impl(S1 const&, S2 const&) { + constexpr char const* s1 = S1::get(); + constexpr char const* s2 = S2::get(); + return bool_; + } + }; +}} // end namespace boost::hana + +#endif // !BOOST_HANA_STRING_ORDERABLE_HPP diff --git a/include/boost/hana/string/string.hpp b/include/boost/hana/string/string.hpp index 9e48812fa..81c305e33 100644 --- a/include/boost/hana/string/string.hpp +++ b/include/boost/hana/string/string.hpp @@ -12,6 +12,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include +#include namespace boost { namespace hana { @@ -19,8 +20,8 @@ namespace boost { namespace hana { //! Represents a compile-time string. //! //! ## Instance of - //! `Comparable`, `Constant` - struct String { struct hana_enabled_operators : Comparable { }; }; + //! `Comparable`, `Orderable`, `Constant`, `Foldable` + struct String { struct hana_enabled_operators : Comparable, Orderable { }; }; //! Create a compile-time string from a string literal `s`. //! @relates String diff --git a/test/string/foldable.cpp b/test/string/foldable.cpp new file mode 100644 index 000000000..13f49e209 --- /dev/null +++ b/test/string/foldable.cpp @@ -0,0 +1,67 @@ +/* +@copyright Louis Dionne 2014 +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 +#include +using namespace boost::hana; + + +int main() { + BOOST_HANA_CONSTEXPR_LAMBDA auto f = test::injection([]{}); + + // unpack + { + BOOST_HANA_CONSTANT_ASSERT(equal( + unpack(BOOST_HANA_STRING(""), f), + f() + )); + BOOST_HANA_CONSTANT_ASSERT(equal( + unpack(BOOST_HANA_STRING("a"), f), + f(char_<'a'>) + )); + BOOST_HANA_CONSTANT_ASSERT(equal( + unpack(BOOST_HANA_STRING("ab"), f), + f(char_<'a'>, char_<'b'>) + )); + BOOST_HANA_CONSTANT_ASSERT(equal( + unpack(BOOST_HANA_STRING("abc"), f), + f(char_<'a'>, char_<'b'>, char_<'c'>) + )); + BOOST_HANA_CONSTANT_ASSERT(equal( + unpack(BOOST_HANA_STRING("abcd"), f), + f(char_<'a'>, char_<'b'>, char_<'c'>, char_<'d'>) + )); + BOOST_HANA_CONSTANT_ASSERT(equal( + unpack(BOOST_HANA_STRING("abcde"), f), + f(char_<'a'>, char_<'b'>, char_<'c'>, char_<'d'>, char_<'e'>) + )); + } + + // length + { + BOOST_HANA_CONSTANT_ASSERT(equal(length(BOOST_HANA_STRING("")), int_<0>)); + BOOST_HANA_CONSTANT_ASSERT(equal(length(BOOST_HANA_STRING("a")), int_<1>)); + BOOST_HANA_CONSTANT_ASSERT(equal(length(BOOST_HANA_STRING("ab")), int_<2>)); + BOOST_HANA_CONSTANT_ASSERT(equal(length(BOOST_HANA_STRING("abc")), int_<3>)); + } + + // laws + { + BOOST_HANA_CONSTANT_ASSERT(Foldable_laws( + BOOST_HANA_STRING(""), + BOOST_HANA_STRING("a"), + BOOST_HANA_STRING("ab"), + BOOST_HANA_STRING("abc"), + BOOST_HANA_STRING("abcd"), + BOOST_HANA_STRING("abcde") + )); + } +} diff --git a/test/string/orderable.cpp b/test/string/orderable.cpp new file mode 100644 index 000000000..b0d5579cf --- /dev/null +++ b/test/string/orderable.cpp @@ -0,0 +1,66 @@ +/* +@copyright Louis Dionne 2014 +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 +using namespace boost::hana; + + +int main() { + // less + { + BOOST_HANA_CONSTANT_ASSERT(not_(less( + BOOST_HANA_STRING(""), + BOOST_HANA_STRING("") + ))); + + BOOST_HANA_CONSTANT_ASSERT(less( + BOOST_HANA_STRING(""), + BOOST_HANA_STRING("a") + )); + + BOOST_HANA_CONSTANT_ASSERT(not_(less( + BOOST_HANA_STRING("a"), + BOOST_HANA_STRING("") + ))); + + BOOST_HANA_CONSTANT_ASSERT(less( + BOOST_HANA_STRING("a"), + BOOST_HANA_STRING("ab") + )); + + BOOST_HANA_CONSTANT_ASSERT(not_(less( + BOOST_HANA_STRING("ab"), + BOOST_HANA_STRING("ab") + ))); + + BOOST_HANA_CONSTANT_ASSERT(less( + BOOST_HANA_STRING("abc"), + BOOST_HANA_STRING("abcde") + )); + + BOOST_HANA_CONSTANT_ASSERT(less( + BOOST_HANA_STRING("abcde"), + BOOST_HANA_STRING("abfde") + )); + } + + // laws + { + BOOST_HANA_CONSTANT_ASSERT(Orderable_laws( + BOOST_HANA_STRING(""), + BOOST_HANA_STRING("a"), + BOOST_HANA_STRING("ab"), + BOOST_HANA_STRING("ba"), + BOOST_HANA_STRING("abc"), + BOOST_HANA_STRING("abcd"), + BOOST_HANA_STRING("afcd") + )); + } +}