diff --git a/doc/src/refmanual/c_str.rst b/doc/src/refmanual/c_str.rst new file mode 100644 index 0000000..8f0ea4e --- /dev/null +++ b/doc/src/refmanual/c_str.rst @@ -0,0 +1,108 @@ +.. Metafunctions/String Operations//c_str |10 + +.. Copyright Eric Niebler 2009. +.. 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) + +c_str +===== + +Synopsis +-------- + +.. parsed-literal:: + + template< + typename Sequence + > + struct c_str + { + typedef |unspecified| type; + static char const value[]; + }; + + +Description +----------- + +``c_str`` converts the |Forward Sequence| of |Integral Constant|\ s ``Sequence`` +into a null-terminated byte string containing an equivalent sequence. + + +Header +------ + +.. parsed-literal:: + + #include + + +Model of +-------- + +|Metafunction| + + +Parameters +---------- + ++---------------+---------------------------+-----------------------------------------------+ +| Parameter | Requirement | Description | ++===============+===========================+===============================================+ +| ``Sequence`` | |Forward Sequence| of | A sequence to be converted into a | +| | |Integral Constant|\ s | null-terminated byte string. | ++---------------+---------------------------+-----------------------------------------------+ + + +Expression semantics +-------------------- + +.. compound:: + :class: expression-semantics + + For any |Forward Sequence| of |Integral Constant|\ s ``s``, + + .. parsed-literal:: + + c_str::value; + + :Return type: + A null-terminated byte string. + + :Precondition: + ``size::value <= BOOST_MPL_STRING_MAX_LENGTH``. + + :Semantics: + Equivalent to + + .. parsed-literal:: + + char const value[] = { + at::type::value + , ... + , at::value-1>::type::value + , '\\0' + }; + +Complexity +---------- + ++-------------------------------+-----------------------------------+ +| Sequence archetype | Complexity | ++===============================+===================================+ +| |Forward Sequence| | Linear. | ++-------------------------------+-----------------------------------+ + +Example +------- + +.. parsed-literal:: + + typedef vector_c hello; + assert( 0 == std::strcmp( c_str::value, "hello" ) ); + +See also +-------- + +|Forward Sequence|, |Integral Constant|, |string| diff --git a/doc/src/refmanual/refmanual.toc b/doc/src/refmanual/refmanual.toc index caad192..93b115a 100644 --- a/doc/src/refmanual/refmanual.toc +++ b/doc/src/refmanual/refmanual.toc @@ -23,6 +23,7 @@ Metafunctions/Comparisons Metafunctions/Logical Operations Metafunctions/Bitwise Operations Metafunctions/Trivial +Metafunctions/String Operations Metafunctions/Miscellaneous Data Types Data Types/Concepts diff --git a/doc/src/refmanual/string.rst b/doc/src/refmanual/string.rst index 57a58a3..833762b 100644 --- a/doc/src/refmanual/string.rst +++ b/doc/src/refmanual/string.rst @@ -11,14 +11,15 @@ string Description ----------- -``string`` is a |variadic|, `random access`__, `extensible`__ |Integral Sequence Wrapper| of +``string`` is a |variadic|, `bidirectional`__, `extensible`__ |Integral Sequence Wrapper| of characters that supports constant-time insertion and removal of elements at both ends, and linear-time insertion and removal of elements in the middle. The parameters to ``string`` are multi-character literals, giving a somewhat readable syntax for compile-time strings. -``string`` also has a class static null-terminated character array called ``c_str`` that -facilitates interoperability with runtime string processing routines. +``string`` can also be an argument to the ``c_str`` metafunction, which generates a +null-terminated character array that facilitates interoperability with runtime string +processing routines. -__ `Random Access Sequence`_ +__ `Bidirectional Sequence`_ __ `Extensible Sequence`_ Header @@ -35,12 +36,11 @@ Model of * |Integral Sequence Wrapper| * |Variadic Sequence| -* |Random Access Sequence| +* |Bidirectional Sequence| * |Extensible Sequence| * |Back Extensible Sequence| * |Front Extensible Sequence| - Expression semantics -------------------- @@ -60,24 +60,21 @@ and |c1...cn| are arbitrary (multi-)characters. | string<|c1...cn|>::type | | +---------------------------------------+-----------------------------------------------------------+ | ``begin::type`` | An iterator pointing to the beginning of ``s``; | -| | see |Random Access Sequence|. | +| | see |Bidirectional Sequence|. | +---------------------------------------+-----------------------------------------------------------+ | ``end::type`` | An iterator pointing to the end of ``s``; | -| | see |Random Access Sequence|. | +| | see |Bidirectional Sequence|. | +---------------------------------------+-----------------------------------------------------------+ -| ``size::type`` | The size of ``s``; see |Random Access Sequence|. | +| ``size::type`` | The size of ``s``; see |Bidirectional Sequence|. | +---------------------------------------+-----------------------------------------------------------+ | ``empty::type`` | |true if and only if| the sequence is empty; | -| | see |Random Access Sequence|. | +| | see |Bidirectional Sequence|. | +---------------------------------------+-----------------------------------------------------------+ | ``front::type`` | The first element in ``s``; see | -| | |Random Access Sequence|. | +| | |Bidirectional Sequence|. | +---------------------------------------+-----------------------------------------------------------+ | ``back::type`` | The last element in ``s``; see | -| | |Random Access Sequence|. | -+---------------------------------------+-----------------------------------------------------------+ -| ``at::type`` | The ``n``\ th element from the beginning of ``s``; see | -| | |Random Access Sequence|. | +| | |Bidirectional Sequence|. | +---------------------------------------+-----------------------------------------------------------+ | ``insert::type`` | A new ``string`` of following elements: | | | [``begin::type``, ``pos``), ``x``, | @@ -114,11 +111,10 @@ and |c1...cn| are arbitrary (multi-)characters. | | [``next< begin::type >::type``, ``end::type``); | | | see |Front Extensible Sequence|. | +---------------------------------------+-----------------------------------------------------------+ -| ``s::c_str`` | A null-terminated byte string such that | -| | ``s::c_str[``\ *n*\ ``]`` is | -| | ``at::type::value`` for each *n* in | -| | [``0``, ``size::type::value``), and | -| | ``s::c_str[size::type::value]`` is ``'\0'``. | +| ``c_str::value`` | A null-terminated byte string such that | +| | ``c_str::value[``\ *n*\ ``]`` is equal to the *n*\ -th | +| | character in ``s``, and | +| | ``c_str::value[size::type::value]`` is ``'\0'``. | +---------------------------------------+-----------------------------------------------------------+ @@ -127,14 +123,13 @@ Example .. parsed-literal:: - typedef string<'hell','o wo','rld'> hello; - typedef push_back >::type hello2; + typedef mpl::string<'hell','o wo','rld'> hello; + typedef mpl::push_back >::type hello2; - BOOST_ASSERT(0 == std::strcmp(hello2::c_str, "hello world!")); + BOOST_ASSERT(0 == std::strcmp(mpl::c_str::value, "hello world!")); See also -------- -|Sequences|, |Variadic Sequence|, |Random Access Sequence|, |Extensible Sequence|, |Integral Sequence Wrapper|, |char_| - +|Sequences|, |Variadic Sequence|, |Bidirectional Sequence|, |Extensible Sequence|, |Integral Sequence Wrapper|, |char_|, |c_str| diff --git a/include/boost/mpl/string.hpp b/include/boost/mpl/string.hpp index 1ab7d33..885059f 100644 --- a/include/boost/mpl/string.hpp +++ b/include/boost/mpl/string.hpp @@ -4,8 +4,8 @@ // Copyright Eric Niebler 2009 // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// 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) // // See http://www.boost.org/libs/mpl for documentation. @@ -14,23 +14,21 @@ // $Date: 2009-04-01 02:10:26 -0700 (Wed, 1 Apr 2009) $ // $Revision: 49239 $ -#include -#include #include -#include -#include #include +#include #include #include #include #include #include +#include #include #include #include #include -#include #include +#include #include #include #include @@ -42,7 +40,7 @@ namespace boost { namespace mpl #ifndef BOOST_MPL_STRING_MAX_LENGTH # define BOOST_MPL_STRING_MAX_LENGTH 32 #endif - + #define BOOST_MPL_STRING_MAX_PARAMS BOOST_PP_DIV(BOOST_PP_ADD(BOOST_MPL_STRING_MAX_LENGTH, 3), 4) #define BOOST_MPL_MULTICHAR_LENGTH(c) (std::size_t)((c>0xffffff)+(c>0xffff)+(c>0xff)+1) @@ -51,10 +49,10 @@ namespace boost { namespace mpl struct string_tag; struct string_iterator_tag; - template + template struct string; - template + template struct string_iterator; template @@ -64,36 +62,40 @@ namespace boost { namespace mpl struct size_impl; template<> - struct size_impl + struct size_impl { template - struct apply - : mpl::size_t - {}; - }; + struct apply; - template - struct at_impl; + #define M0(z, n, data) \ + + BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C,n)) + + #define M1(z, n, data) \ + template \ + struct apply > \ + : mpl::size_t<(0 BOOST_PP_REPEAT_ ## z(n, M0, ~))> \ + {}; + + BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M1, ~) + #undef M0 + #undef M1 + }; template<> - struct at_impl - { - template - struct apply - : Sequence::template at - {}; - }; + struct size_impl::apply > + : mpl::size_t<0> + {}; template struct begin_impl; template<> - struct begin_impl + struct begin_impl { template struct apply { - typedef string_iterator type; + typedef mpl::string_iterator type; }; }; @@ -101,102 +103,212 @@ namespace boost { namespace mpl struct end_impl; template<> - struct end_impl + struct end_impl { template - struct apply - { - typedef string_iterator type; + struct apply; + + #define M0(z,n,data) \ + template \ + struct apply > \ + { \ + typedef mpl::string_iterator, n, 0> type; \ }; + + BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) + #undef M0 + }; + + template<> + struct end_impl::apply > + { + typedef mpl::string_iterator, 0, 0> type; }; template struct push_back_impl; template<> - struct push_back_impl + struct push_back_impl { template struct apply { - BOOST_MPL_ASSERT_MSG(false, PUSH_BACK_FAILED_MPL_STRING_IS_FULL, (Sequence)); - typedef void type; + BOOST_MPL_ASSERT_MSG( + (BOOST_MPL_STRING_MAX_LENGTH != mpl::size::type::value) + , PUSH_BACK_FAILED_MPL_STRING_IS_FULL + , (Sequence) + ); + // If the above assertion didn't fire, then the string is sparse. + // Repack the string and retry the push_back + typedef + typename mpl::push_back< + typename mpl::copy< + Sequence + , mpl::back_inserter > + >::type + , Value + >::type + type; }; template - struct apply, Value, false> + struct apply, Value, false> { - typedef string<(char)Value::value> type; + typedef mpl::string<(char)Value::value> type; }; #define M0(z,n,data) \ - template \ - struct apply, Value, false> \ + template \ + struct apply, Value, false> \ { \ - typedef string< \ - BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \ - BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ - (BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \ - ?BOOST_PP_CAT(C,BOOST_PP_DEC(n)) \ - :(BOOST_PP_CAT(C,BOOST_PP_DEC(n))<<8)|(unsigned char)Value::value \ - , (BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \ - ?(char)Value::value \ - :0 \ - > type; \ + typedef \ + mpl::string< \ + BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \ + BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + (BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \ + ?BOOST_PP_CAT(C,BOOST_PP_DEC(n)) \ + :(BOOST_PP_CAT(C,BOOST_PP_DEC(n))<<8)|(unsigned char)Value::value \ + , (BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \ + ?(char)Value::value \ + :0 \ + > \ + type; \ }; BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) #undef M0 - template - struct apply, Value, false> + template + struct apply, Value, false> { - typedef string< - BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), C) - , (BOOST_PP_CAT(C,BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS))<<8)|(unsigned char)Value::value - > type; + typedef + mpl::string< + BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), C) + , (BOOST_PP_CAT(C,BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS))<<8)|(unsigned char)Value::value + > + type; }; }; + template + struct pop_back_impl; + + template<> + struct pop_back_impl + { + template + struct apply; + + #define M0(z,n,data) \ + template \ + struct apply > \ + { \ + BOOST_MPL_ASSERT_MSG((C0 != 0), POP_BACK_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \ + typedef \ + mpl::string< \ + BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \ + BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + (BOOST_PP_CAT(C,BOOST_PP_DEC(n))>>8) \ + > \ + type; \ + }; + + BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) + #undef M0 + }; + template struct push_front_impl; template<> - struct push_front_impl + struct push_front_impl { template struct apply { - BOOST_MPL_ASSERT_MSG(false, PUSH_FRONT_FAILED_MPL_STRING_IS_FULL, (Sequence)); - typedef void type; + BOOST_MPL_ASSERT_MSG( + (BOOST_MPL_STRING_MAX_LENGTH != mpl::size::type::value) + , PUSH_FRONT_FAILED_MPL_STRING_IS_FULL + , (Sequence) + ); + // If the above assertion didn't fire, then the string is sparse. + // Repack the string and retry the push_front. + typedef + typename mpl::push_front< + typename mpl::reverse_copy< + Sequence + , mpl::front_inserter > + >::type + , Value + >::type + type; }; template - struct apply, Value, false> + struct apply, Value, false> { - typedef string<(char)Value::value> type; + typedef mpl::string<(char)Value::value> type; }; #define M0(z,n,data) \ - template \ - struct apply, Value, true> \ + template \ + struct apply, Value, true> \ { \ - typedef string< \ - (char)Value::value \ - BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, C) \ - > type; \ + typedef \ + mpl::string< \ + (char)Value::value \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, C) \ + > \ + type; \ }; BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) #undef M0 - template - struct apply, Value, false> + template + struct apply, Value, false> { - typedef string< - ((((unsigned char)Value::value)<<(BOOST_MPL_MULTICHAR_LENGTH(C0)*8))|C0) - , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C) - > type; + typedef + mpl::string< + ((((unsigned char)Value::value)<<(BOOST_MPL_MULTICHAR_LENGTH(C0)*8))|C0) + , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C) + > + type; + }; + }; + + template + struct pop_front_impl; + + template<> + struct pop_front_impl + { + template + struct apply; + + #define M0(z,n,data) \ + template \ + struct apply, true> \ + { \ + BOOST_MPL_ASSERT_MSG((C0 != 0), POP_FRONT_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \ + typedef \ + mpl::string \ + type; \ + }; + + BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) + #undef M0 + + template + struct apply, false> + { + typedef + mpl::string< + (((1<<((BOOST_MPL_MULTICHAR_LENGTH(C0)-1)*8))-1)&C0) + , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C) + > + type; }; }; @@ -204,25 +316,25 @@ namespace boost { namespace mpl struct insert_range_impl; template<> - struct insert_range_impl + struct insert_range_impl { template struct apply - : copy< - joint_view< - iterator_range< - string_iterator + : mpl::copy< + mpl::joint_view< + mpl::iterator_range< + mpl::string_iterator , Pos > - , joint_view< + , mpl::joint_view< Range - , iterator_range< + , mpl::iterator_range< Pos - , string_iterator + , typename mpl::end::type > > > - , back_inserter > + , mpl::back_inserter > > {}; }; @@ -231,11 +343,11 @@ namespace boost { namespace mpl struct insert_impl; template<> - struct insert_impl + struct insert_impl { template struct apply - : insert_range > + : mpl::insert_range > {}; }; @@ -243,22 +355,22 @@ namespace boost { namespace mpl struct erase_impl; template<> - struct erase_impl + struct erase_impl { template struct apply - : copy< - joint_view< - iterator_range< - string_iterator + : mpl::copy< + mpl::joint_view< + mpl::iterator_range< + mpl::string_iterator , First > - , iterator_range< - typename if_na::type>::type - , string_iterator + , mpl::iterator_range< + typename mpl::if_na::type>::type + , typename mpl::end::type > > - , back_inserter > + , mpl::back_inserter > > {}; }; @@ -267,152 +379,122 @@ namespace boost { namespace mpl struct clear_impl; template<> - struct clear_impl + struct clear_impl { template struct apply { - typedef string<> type; + typedef mpl::string<> type; }; }; - template - struct advance_impl; - - template<> - struct advance_impl - { - template - struct apply - { - typedef string_iterator< - typename Iterator::string_type - , Iterator::index + N::value - > type; - }; + #define M0(z, n, data) \ + template \ + struct string_iterator, n, J> \ + { \ + typedef mpl::string string; \ + typedef std::bidirectional_iterator_tag category; \ + typedef \ + typename mpl::if_c< \ + (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == J + 1) \ + , mpl::string_iterator \ + , mpl::string_iterator \ + >::type \ + next; \ + typedef \ + mpl::string_iterator \ + prior; \ + typedef mpl::char_ type; \ + }; \ + template \ + struct string_iterator, n, 0> \ + { \ + typedef mpl::string string; \ + typedef std::bidirectional_iterator_tag category; \ + typedef \ + typename mpl::if_c< \ + (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == 1) \ + , mpl::string_iterator \ + , mpl::string_iterator \ + >::type \ + next; \ + typedef \ + mpl::string_iterator< \ + string \ + , n - 1 \ + , BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, BOOST_PP_DEC(n))) - 1 \ + > \ + prior; \ + typedef mpl::char_ type; \ }; - template - struct distance_impl; + BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_PARAMS, M0, ~) + #undef M0 - template<> - struct distance_impl - { - template - struct apply - { - typedef mpl::long_<(long)Last::index - (long)First::index> type; - }; - }; - - template - struct string_iterator - : Sequence::template at - { - typedef string_iterator_tag tag; - typedef std::random_access_iterator_tag category; - typedef Sequence string_type; - static unsigned long const index = N; - typedef string_iterator next; - typedef string_iterator prior; - }; - - template + template struct string { /// INTERNAL ONLY - static unsigned int const front_ = C0; - /// INTERNAL ONLY - static unsigned int const back_ = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)); - /// INTERNAL ONLY - typedef string rest_; + enum + { + front_ = C0 + , back_ = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)) + }; - typedef string type; - - typedef string_tag tag; - - static std::size_t const size = BOOST_MPL_MULTICHAR_LENGTH(C0) + rest_::size; - - #if BOOST_WORKAROUND(BOOST_MSVC, <= 1400) - private: - /// INTERNAL ONLY - template - struct at_impl - : boost::mpl::char_ - {}; - - /// INTERNAL ONLY - template - struct at_impl - : rest_::template at - {}; - - public: - template - struct at - : at_impl - {}; - #else - template - struct at - : boost::mpl::char_ - {}; - - template - struct at - : rest_::template at - {}; - #endif - - static char const c_str[]; + typedef string type; + typedef string_tag tag; }; - template - char const string::c_str[] = + namespace aux_ { - #define M0(z, n, data) at::value - BOOST_PP_ENUM(BOOST_MPL_STRING_MAX_LENGTH, M0, ~) - #undef M0 - , '\0' // to ensure the string is null-terminated - }; - - template - std::size_t const string::size; - - template - unsigned int const string::front_; - - template - unsigned int const string::back_; - - template<> - struct string<> - { - /// INTERNAL ONLY - static unsigned int const front_ = 0; - /// INTERNAL ONLY - static unsigned int const back_ = 0; - /// INTERNAL ONLY - typedef string rest_; - - typedef string type; - - typedef string_tag tag; - - static std::size_t const size = 0; - - template - struct at - : boost::mpl::char_<'\0'> + template + struct next_unless + : mpl::next {}; - static char const c_str[]; + template + struct next_unless + { + typedef End type; + }; + + template + struct deref_unless + : mpl::deref + {}; + + template + struct deref_unless + { + typedef mpl::char_<'\0'> type; + }; + } + + template + struct c_str + { + typedef typename mpl::end::type iend; + typedef typename mpl::begin::type i0; + #define M0(z, n, data) \ + typedef \ + typename mpl::aux_::next_unless::type \ + BOOST_PP_CAT(i, BOOST_PP_INC(n)); + BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_LENGTH, M0, ~) + #undef M0 + + typedef c_str type; + static char const value[]; }; - char const string<>::c_str[] = {'\0'}; - std::size_t const string<>::size; - unsigned int const string<>::front_; - unsigned int const string<>::back_; + template + char const c_str::value[] = + { + #define M0(z, n, data) \ + mpl::aux_::deref_unless::type::value, + BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_LENGTH, M0, ~) + #undef M0 + '\0' + }; }} // namespace boost diff --git a/test/string.cpp b/test/string.cpp index 4976887..bc6e23c 100644 --- a/test/string.cpp +++ b/test/string.cpp @@ -17,27 +17,21 @@ #include -#include -#include #include -#include -#include #include #include -#include #include #include -#include -#include +#include #include #include +#include +#include #include -#include -#include -#include -#include +#include #include #include + namespace mpl = boost::mpl; // Accept a string as a template parameter! @@ -64,18 +58,287 @@ struct push_char std::string *str_; }; -void test1() +int main() { - BOOST_TEST(0 == std::strcmp(mpl::string<'Hell','o wo','rld!'>::c_str, "Hello world!")); - BOOST_TEST((12 == mpl::size >::type::value)); - BOOST_TEST(('w' == mpl::at_c, 6>::type::value)); + // Test mpl::size of strings + { + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> full; + + BOOST_MPL_ASSERT_RELATION(0, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(1, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(2, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(2, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(4, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(5, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(31, ==, (mpl::size::value)); + BOOST_MPL_ASSERT_RELATION(32, ==, (mpl::size::value)); + } + + // Test mpl::begin and mpl::end with strings + { + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> full; + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::begin >::type + , mpl::end >::type + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::begin >::type + , mpl::string_iterator, 0, 0> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::end >::type + , mpl::string_iterator, 1, 0> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::begin::type + , mpl::string_iterator + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::end::type + , mpl::string_iterator + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::begin::type + , mpl::string_iterator + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::end::type + , mpl::string_iterator + > + )); + } + + // testing push_back + { + typedef mpl::push_back, mpl::char_<'a'> >::type t1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; + typedef mpl::push_back >::type t6; + BOOST_MPL_ASSERT((boost::is_same >)); + } + + // Test mpl::next + { + typedef mpl::string<'a','bc','def','ghij'> s; + + typedef mpl::begin::type i0; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i6; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i7; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i8; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i9; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i10; + BOOST_MPL_ASSERT((boost::is_same >)); + + BOOST_MPL_ASSERT((boost::is_same::type>)); + } + + // Test mpl::prior + { + typedef mpl::string<'a','bc','def','ghij'> s; + + typedef mpl::end::type i10; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i9; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i8; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i7; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i6; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i0; + BOOST_MPL_ASSERT((boost::is_same >)); + + BOOST_MPL_ASSERT((boost::is_same::type>)); + } + + // Test mpl::deref + { + typedef mpl::string<'a','bc','def','ghij'> s; + + typedef mpl::begin::type i0; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'a'> >)); + + typedef mpl::next::type i1; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'b'> >)); + + typedef mpl::next::type i2; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'c'> >)); + + typedef mpl::next::type i3; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'d'> >)); + + typedef mpl::next::type i4; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'e'> >)); + + typedef mpl::next::type i5; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'f'> >)); + + typedef mpl::next::type i6; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'g'> >)); + + typedef mpl::next::type i7; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'h'> >)); + + typedef mpl::next::type i8; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'i'> >)); + + typedef mpl::next::type i9; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'j'> >)); + } + + // testing push_back + { + typedef mpl::push_back, mpl::char_<'a'> >::type t1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; + typedef mpl::push_back >::type t6; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'a','a','a','a','a','a','a','aaaa'> must_repack; + typedef mpl::push_back >::type t7; + BOOST_MPL_ASSERT((boost::is_same >)); + } + + // testing push_front + { + typedef mpl::push_front, mpl::char_<'a'> >::type t1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_front >::type t2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_front >::type t3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_front >::type t4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_front >::type t5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> almost_full; + typedef mpl::push_front >::type t6; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'aaaa','a','a','a','a','a','a','a'> must_repack; + typedef mpl::push_front >::type t7; + BOOST_MPL_ASSERT((boost::is_same >)); + } + + // Test c_str<> + BOOST_TEST(0 == std::strcmp( + mpl::c_str >::value + , "" + )); + + BOOST_TEST(0 == std::strcmp( + mpl::c_str >::value + , "Hell" "o wo" "rld!" + )); + + BOOST_TEST(0 == std::strcmp( + mpl::c_str >::value + , "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaX" + )); // test using a string as a template parameter - greeting::c_str> g; + greeting >::value> g; BOOST_TEST("Hello world!" == g.say_hello()); - BOOST_TEST(0 == std::strcmp("", mpl::string<>::c_str)); - std::string result; mpl::for_each >(push_char(result)); BOOST_TEST("Hello world!" == result); @@ -85,89 +348,128 @@ void test1() BOOST_TEST(('h' == mpl::front >::type())); BOOST_TEST(('!' == mpl::back >::type())); -} -// testing push_back -void test2() -{ - typedef mpl::push_back, mpl::char_<'a'> >::type t1; - BOOST_TEST(0 == std::strcmp("a", t1::c_str)); - - typedef mpl::push_back >::type t2; - BOOST_TEST(0 == std::strcmp("ab", t2::c_str)); - - typedef mpl::push_back >::type t3; - BOOST_TEST(0 == std::strcmp("abc", t3::c_str)); - BOOST_MPL_ASSERT((boost::is_same >)); - - typedef mpl::push_back >::type t4; - BOOST_TEST(0 == std::strcmp("abcd", t4::c_str)); - - typedef mpl::push_back >::type t5; - BOOST_TEST(0 == std::strcmp("abcde", t5::c_str)); - BOOST_MPL_ASSERT((boost::is_same >)); - - typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; - BOOST_TEST(0 == std::strcmp("aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaa", almost_full::c_str)); - - typedef mpl::push_back >::type t6; - BOOST_TEST(0 == std::strcmp("aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaX", t6::c_str)); -} - -// testing push_front -void test3() -{ - typedef mpl::push_front, mpl::char_<'a'> >::type t1; - BOOST_TEST(0 == std::strcmp("a", t1::c_str)); - - typedef mpl::push_front >::type t2; - BOOST_TEST(0 == std::strcmp("ba", t2::c_str)); - - typedef mpl::push_front >::type t3; - BOOST_TEST(0 == std::strcmp("cba", t3::c_str)); - - typedef mpl::push_front >::type t4; - BOOST_TEST(0 == std::strcmp("dcba", t4::c_str)); - - typedef mpl::push_front >::type t5; - BOOST_TEST(0 == std::strcmp("edcba", t5::c_str)); - - typedef mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> almost_full; - BOOST_TEST(0 == std::strcmp("aaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa", almost_full::c_str)); - - typedef mpl::push_front >::type t6; - BOOST_TEST(0 == std::strcmp("Xaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa", t6::c_str)); -} - -void test4() -{ // back-inserter with copy typedef mpl::vector_c rgc; + BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str::value)); typedef mpl::copy > >::type str; - BOOST_TEST(0 == std::strcmp("abcde", str::c_str)); -} + BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str::value)); -// test insert_range and erase -void test5() -{ - typedef mpl::string<'Hell','o wo','rld!'> hello; - typedef mpl::advance_c::type, 5>::type where; - typedef mpl::string<' cru','el'> cruel; - typedef mpl::insert_range::type hello_cruel; - BOOST_TEST(0 == std::strcmp("Hello cruel world!", hello_cruel::c_str)); + // test insert_range and erase + { + typedef mpl::string<'Hell','o wo','rld!'> hello; + typedef mpl::advance_c::type, 5>::type where; + typedef mpl::string<' cru','el'> cruel; + typedef mpl::insert_range::type hello_cruel; + BOOST_TEST(0 == std::strcmp("Hello cruel world!", mpl::c_str::value)); - typedef mpl::erase::type, where>::type erased1; - BOOST_TEST(0 == std::strcmp(" world!", erased1::c_str)); -} + typedef mpl::erase::type, where>::type erased1; + BOOST_TEST(0 == std::strcmp(" world!", mpl::c_str::value)); + } + // test pop_front + { + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<> + > + )); -int main() -{ - test1(); - test2(); - test3(); - test4(); - test5(); + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'b'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'bc'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'bcd'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'bcd','e'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'e'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> + > + )); + } + + // test pop_back + { + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'a'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'ab'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'abc'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'abcd'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'d'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> + > + )); + } return boost::report_errors(); }