diff --git a/doc/BOOST_METAPARSE_STRING.qbk b/doc/BOOST_METAPARSE_STRING.qbk index 5168e4a..28b65a2 100644 --- a/doc/BOOST_METAPARSE_STRING.qbk +++ b/doc/BOOST_METAPARSE_STRING.qbk @@ -21,6 +21,10 @@ string literal. The macro requires C++11. The maximal length of the string is limited. This limit is defined by the `BOOST_METAPARSE_LIMIT_STRING_SIZE` macro. +For C++17 and later, consider using +[link BOOST_METAPARSE_STRING_VALUE `BOOST_METAPARSE_STRING_VALUE`] +instead, as it doesn't have these limitations. + On platforms where `BOOST_METAPARSE_STRING` is not supported, the `string.hpp` header defines the `BOOST_METAPARSE_V1_CONFIG_NO_BOOST_METAPARSE_STRING` macro. Defining this macro before including the header disables the diff --git a/doc/BOOST_METAPARSE_STRING_VALUE.qbk b/doc/BOOST_METAPARSE_STRING_VALUE.qbk index 0c14e4d..1982c00 100644 --- a/doc/BOOST_METAPARSE_STRING_VALUE.qbk +++ b/doc/BOOST_METAPARSE_STRING_VALUE.qbk @@ -16,7 +16,15 @@ This is a macro. [h1 Description] This is a convenience macro for creating instances of the string types created -using [link BOOST_METAPARSE_STRING `BOOST_METAPARSE_STRING`]. +using [link BOOST_METAPARSE_STRING `BOOST_METAPARSE_STRING`]. The macro +requires C++11. + +[*C++11]: The maximum length of these strings is controlled by the +`BOOST_METAPARSE_LIMIT_STRING_SIZE` macro. + +[*C++17]: The macro uses constexpr string literal. + +[caution It is [*not recommended] to use an expression with BOOST_METAPARSE_STRING_VALUE as the argument of `decltype`, for example `decltype(BOOST_METAPARSE_STRING_VALUE("foo"))`. Although such constructs may compile successfully in some environments, they tend to be [*non-portable]. ] [h1 Header] diff --git a/include/boost/metaparse/config.hpp b/include/boost/metaparse/config.hpp index f1af39e..8d59546 100644 --- a/include/boost/metaparse/config.hpp +++ b/include/boost/metaparse/config.hpp @@ -40,8 +40,11 @@ || (defined _MSC_VER && _MSC_VER >= 1900) \ ) \ && (!defined BOOST_GCC || BOOST_GCC >= 40700) +# if !defined BOOST_NO_CXX17_DEDUCTION_GUIDES -# if !defined BOOST_NO_CXX14_CONSTEXPR +# define BOOST_METAPARSE_STD 2017 + +# elif !defined BOOST_NO_CXX14_CONSTEXPR # define BOOST_METAPARSE_STD 2014 diff --git a/include/boost/metaparse/v1/cpp17/impl/convert_string.hpp b/include/boost/metaparse/v1/cpp17/impl/convert_string.hpp new file mode 100644 index 0000000..44bfbbb --- /dev/null +++ b/include/boost/metaparse/v1/cpp17/impl/convert_string.hpp @@ -0,0 +1,35 @@ +#ifndef BOOST_METAPARSE_V1_CPP17_IMPL_CONVERT_STRING_HPP +#define BOOST_METAPARSE_V1_CPP17_IMPL_CONVERT_STRING_HPP + +// Copyright Denis Mikhailov 2025. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#include // for std::size_t +#include // for std::make_index_sequence + +namespace boost +{ + namespace metaparse + { + namespace v1 + { + namespace impl + { + template + struct convert_string { + template + static constexpr auto apply(std::index_sequence) noexcept { + return ::boost::metaparse::v1::string{}; + } + }; + } + } + } +} + +#endif + diff --git a/include/boost/metaparse/v1/cpp17/string_value.hpp b/include/boost/metaparse/v1/cpp17/string_value.hpp new file mode 100644 index 0000000..4d38c71 --- /dev/null +++ b/include/boost/metaparse/v1/cpp17/string_value.hpp @@ -0,0 +1,25 @@ +#ifndef BOOST_METAPARSE_V1_CPP17_STRING_VALUE_HPP +#define BOOST_METAPARSE_V1_CPP17_STRING_VALUE_HPP + +// Copyright Denis Mikhailov 2025. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#include // for std::make_index_sequence + +#ifdef BOOST_METAPARSE_V1_STRING_VALUE +#error BOOST_METAPARSE_V1_STRING_VALUE already defined +#endif + +#define BOOST_METAPARSE_V1_STRING_VALUE(s) ([]{ \ + namespace impl = ::boost::metaparse::v1::impl; \ + static constexpr auto fs = impl::make_fixed_string(s); \ + return impl::convert_string::apply(std::make_index_sequence{}); \ +}()) + +#endif + diff --git a/include/boost/metaparse/v1/impl/fixed_string.hpp b/include/boost/metaparse/v1/impl/fixed_string.hpp new file mode 100644 index 0000000..8b9e47f --- /dev/null +++ b/include/boost/metaparse/v1/impl/fixed_string.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_METAPARSE_V1_IMPL_FIXED_STRING_HPP +#define BOOST_METAPARSE_V1_IMPL_FIXED_STRING_HPP + +// Copyright Denis Mikhailov 2025. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include // for std::size_t + +namespace boost +{ + namespace metaparse + { + namespace v1 + { + namespace impl + { + template + struct fixed_string { + const CharT* data; + constexpr fixed_string(const CharT (&s)[N]) noexcept + : data{s} + {} + constexpr CharT operator[](std::size_t i) const noexcept { return data[i]; } + constexpr std::size_t size() const noexcept { return N; } + }; + + template + constexpr fixed_string make_fixed_string(const CharT(&s)[N]) noexcept { + return {s}; + } + } + } + } +} + +#endif + diff --git a/include/boost/metaparse/v1/string_value.hpp b/include/boost/metaparse/v1/string_value.hpp index 6edc6ae..81d64e3 100644 --- a/include/boost/metaparse/v1/string_value.hpp +++ b/include/boost/metaparse/v1/string_value.hpp @@ -2,18 +2,27 @@ #define BOOST_METAPARSE_V1_STRING_VALUE_HPP // Copyright Abel Sinkovics (abel@sinkovics.hu) 2021. +// Copyright Denis Mikhailov 2025. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include -#ifdef BOOST_METAPARSE_V1_STRING_VALUE -#error BOOST_METAPARSE_V1_STRING_VALUE already defined -#endif +#if BOOST_METAPARSE_STD >= 2017 +# include +#else + +# include + +# ifdef BOOST_METAPARSE_V1_STRING_VALUE +# error BOOST_METAPARSE_V1_STRING_VALUE already defined +# endif + +# ifdef BOOST_METAPARSE_V1_STRING +# define BOOST_METAPARSE_V1_STRING_VALUE(s) (BOOST_METAPARSE_V1_STRING(s){}) +# endif -#ifdef BOOST_METAPARSE_V1_STRING -#define BOOST_METAPARSE_V1_STRING_VALUE(s) (BOOST_METAPARSE_V1_STRING(s){}) #endif #endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 286395c..d5149c1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,4 +1,5 @@ import testing ; +import config : requires ; project : requirements @@ -103,6 +104,7 @@ test-suite metaparse-unit-tests : [ compile string_iterator_tag.cpp ] [ compile string_tag.cpp ] [ compile string_value.cpp ] + [ compile string_value_unlimited_cxx17.cpp : [ requires cxx17_deduction_guides ] ] [ compile swap.cpp ] [ compile token.cpp ] [ compile-fail too_long_string.cpp ] diff --git a/test/string_value_unlimited_cxx17.cpp b/test/string_value_unlimited_cxx17.cpp new file mode 100644 index 0000000..1e04069 --- /dev/null +++ b/test/string_value_unlimited_cxx17.cpp @@ -0,0 +1,24 @@ +// Copyright Denis Mikhailov 2025. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE string_value_unlimited_cxx17 + +#define BOOST_METAPARSE_LIMIT_STRING_SIZE 4 +#include +#include + +#include + +#include + +BOOST_AUTO_TEST_CASE(test_string_value_unlimited_cxx17) +{ + auto abcde = BOOST_METAPARSE_STRING_VALUE("abcde"); + + BOOST_MPL_ASSERT(( + std::is_same, decltype(abcde)> + )); +} +