Skip to content

Commit 1aa52a9

Browse files
committed
[string] Add a conversion from a Constant holding a char const*
Closes #347
1 parent ba723f7 commit 1aa52a9

File tree

4 files changed

+130
-9
lines changed

4 files changed

+130
-9
lines changed

example/string/from_c_str.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright Louis Dionne 2013-2017
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/core/to.hpp>
7+
#include <boost/hana/equal.hpp>
8+
#include <boost/hana/integral_constant.hpp>
9+
#include <boost/hana/string.hpp>
10+
namespace hana = boost::hana;
11+
12+
13+
constexpr char const hello[] = "hello";
14+
auto hello_constant = hana::integral_constant<char const*, hello>{};
15+
16+
BOOST_HANA_CONSTANT_CHECK(
17+
hana::to_string(hello_constant) == hana::string_c<'h', 'e', 'l', 'l', 'o'>
18+
);
19+
20+
int main() { }

include/boost/hana/fwd/string.hpp

+21-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Distributed under the Boost Software License, Version 1.0.
1212

1313
#include <boost/hana/config.hpp>
1414
#include <boost/hana/fwd/core/make.hpp>
15+
#include <boost/hana/fwd/core/to.hpp>
1516

1617

1718
BOOST_HANA_NAMESPACE_BEGIN
@@ -94,16 +95,23 @@ BOOST_HANA_NAMESPACE_BEGIN
9495
//! concepts as `hana::string` does.
9596
//! @include example/string/to.cpp
9697
//!
98+
//! Conversion from any Constant holding a `char const*`
99+
//! ----------------------------------------------------
100+
//! A `hana::string` can be created from any `Constant` whose underlying
101+
//! value is convertible to a `char const*` by using `hana::to`. The
102+
//! contents of the `char const*` are used to build the content of the
103+
//! `hana::string`.
104+
//! @include example/string/from_c_str.cpp
97105
//!
98-
//! > #### Rationale for `hana::string` not being a `Constant`
99-
//! > The underlying type held by a `hana::string` could be either
100-
//! > `char const*` or some other constexpr-enabled string-like container.
101-
//! > In the first case, `hana::string` can not be a `Constant` because
102-
//! > the models of several concepts would not be respected by the
103-
//! > underlying type, causing `value` not to be structure-preserving.
104-
//! > Providing an underlying value of constexpr-enabled string-like
105-
//! > container type like `std::string_view` would be great, but that's
106-
//! > a bit complicated for the time being.
106+
//! Rationale for `hana::string` not being a `Constant` itself
107+
//! ----------------------------------------------------------
108+
//! The underlying type held by a `hana::string` could be either `char const*`
109+
//! or some other constexpr-enabled string-like container. In the first case,
110+
//! `hana::string` can not be a `Constant` because the models of several
111+
//! concepts would not be respected by the underlying type, causing `value`
112+
//! not to be structure-preserving. Providing an underlying value of
113+
//! constexpr-enabled string-like container type like `std::string_view`
114+
//! would be great, but that's a bit complicated for the time being.
107115
template <typename implementation_defined>
108116
struct string {
109117
// Default-construct a `hana::string`; no-op since `hana::string` is stateless.
@@ -180,6 +188,10 @@ BOOST_HANA_NAMESPACE_BEGIN
180188
//! @relates hana::string
181189
constexpr auto make_string = make<string_tag>;
182190

191+
//! Equivalent to `to<string_tag>`; provided for convenience.
192+
//! @relates hana::string
193+
constexpr auto to_string = to<string_tag>;
194+
183195
//! Create a compile-time string from a parameter pack of characters.
184196
//! @relates hana::string
185197
//!

include/boost/hana/string.hpp

+30
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Distributed under the Boost Software License, Version 1.0.
1313
#include <boost/hana/fwd/string.hpp>
1414

1515
#include <boost/hana/bool.hpp>
16+
#include <boost/hana/concept/constant.hpp>
1617
#include <boost/hana/config.hpp>
1718
#include <boost/hana/core/make.hpp>
1819
#include <boost/hana/detail/algorithm.hpp>
@@ -147,6 +148,35 @@ BOOST_HANA_NAMESPACE_BEGIN
147148
{ return string<c...>::c_str(); }
148149
};
149150

151+
//////////////////////////////////////////////////////////////////////////
152+
// to<string_tag>
153+
//////////////////////////////////////////////////////////////////////////
154+
namespace detail {
155+
constexpr std::size_t cx_strlen(char const* s) {
156+
std::size_t n = 0u;
157+
while (*s != '\0')
158+
++s, ++n;
159+
return n;
160+
}
161+
162+
template <typename S, std::size_t ...I>
163+
constexpr hana::string<hana::value<S>()[I]...> expand(std::index_sequence<I...>)
164+
{ return {}; }
165+
}
166+
167+
template <typename IC>
168+
struct to_impl<hana::string_tag, IC, hana::when<
169+
hana::Constant<IC>::value &&
170+
std::is_convertible<typename IC::value_type, char const*>::value
171+
>> {
172+
template <typename S>
173+
static constexpr auto apply(S const&) {
174+
constexpr char const* s = hana::value<S>();
175+
constexpr std::size_t len = detail::cx_strlen(s);
176+
return detail::expand<S>(std::make_index_sequence<len>{});
177+
}
178+
};
179+
150180
//////////////////////////////////////////////////////////////////////////
151181
// Comparable
152182
//////////////////////////////////////////////////////////////////////////

test/string/cnstr.c_str.cpp

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright Louis Dionne 2013-2017
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/core/to.hpp>
7+
#include <boost/hana/equal.hpp>
8+
#include <boost/hana/ext/std/integral_constant.hpp>
9+
#include <boost/hana/integral_constant.hpp>
10+
#include <boost/hana/string.hpp>
11+
12+
#include <type_traits>
13+
namespace hana = boost::hana;
14+
15+
16+
constexpr char const empty[] = "";
17+
constexpr char const a[] = "a";
18+
constexpr char const ab[] = "ab";
19+
constexpr char const abc[] = "abc";
20+
constexpr char const abcd[] = "abcd";
21+
22+
int main() {
23+
{
24+
auto string = hana::to<hana::string_tag>(hana::integral_constant<char const*, empty>{});
25+
BOOST_HANA_CONSTANT_CHECK(hana::equal(string, hana::string_c<>));
26+
}
27+
28+
{
29+
auto string = hana::to<hana::string_tag>(hana::integral_constant<char const*, a>{});
30+
BOOST_HANA_CONSTANT_CHECK(hana::equal(string, hana::string_c<'a'>));
31+
}
32+
33+
{
34+
auto string = hana::to<hana::string_tag>(hana::integral_constant<char const*, ab>{});
35+
BOOST_HANA_CONSTANT_CHECK(hana::equal(string, hana::string_c<'a', 'b'>));
36+
}
37+
38+
{
39+
auto string = hana::to<hana::string_tag>(hana::integral_constant<char const*, abc>{});
40+
BOOST_HANA_CONSTANT_CHECK(hana::equal(string, hana::string_c<'a', 'b', 'c'>));
41+
}
42+
43+
{
44+
auto string = hana::to<hana::string_tag>(hana::integral_constant<char const*, abcd>{});
45+
BOOST_HANA_CONSTANT_CHECK(hana::equal(string, hana::string_c<'a', 'b', 'c', 'd'>));
46+
}
47+
48+
// Make sure it also works with std::integral_constant, for example
49+
{
50+
auto string = hana::to<hana::string_tag>(std::integral_constant<char const*, abcd>{});
51+
BOOST_HANA_CONSTANT_CHECK(hana::equal(string, hana::string_c<'a', 'b', 'c', 'd'>));
52+
}
53+
54+
// Make sure the `to_string` shortcut works
55+
{
56+
auto string = hana::to_string(hana::integral_constant<char const*, abcd>{});
57+
BOOST_HANA_CONSTANT_CHECK(hana::equal(string, hana::string_c<'a', 'b', 'c', 'd'>));
58+
}
59+
}

0 commit comments

Comments
 (0)