mpl::string is a bidirectional sequence, not random access; c_str is a separate metafunction, not a class static

[SVN r52314]
This commit is contained in:
Eric Niebler
2009-04-11 05:48:51 +00:00
parent c7025170c7
commit 0ee68a2c76
5 changed files with 821 additions and 333 deletions

108
doc/src/refmanual/c_str.rst Normal file
View File

@@ -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 <boost/mpl/string.hpp>
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<s>::value;
:Return type:
A null-terminated byte string.
:Precondition:
``size<s>::value <= BOOST_MPL_STRING_MAX_LENGTH``.
:Semantics:
Equivalent to
.. parsed-literal::
char const value[] = {
at<s, 0>::type::value
, ...
, at<s, size<s>::value-1>::type::value
, '\\0'
};
Complexity
----------
+-------------------------------+-----------------------------------+
| Sequence archetype | Complexity |
+===============================+===================================+
| |Forward Sequence| | Linear. |
+-------------------------------+-----------------------------------+
Example
-------
.. parsed-literal::
typedef vector_c<char,'h','e','l','l','o'> hello;
assert( 0 == std::strcmp( c_str<hello>::value, "hello" ) );
See also
--------
|Forward Sequence|, |Integral Constant|, |string|

View File

@@ -23,6 +23,7 @@ Metafunctions/Comparisons
Metafunctions/Logical Operations Metafunctions/Logical Operations
Metafunctions/Bitwise Operations Metafunctions/Bitwise Operations
Metafunctions/Trivial Metafunctions/Trivial
Metafunctions/String Operations
Metafunctions/Miscellaneous Metafunctions/Miscellaneous
Data Types Data Types
Data Types/Concepts Data Types/Concepts

View File

@@ -11,14 +11,15 @@ string
Description 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 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`` 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. 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 ``string`` can also be an argument to the ``c_str`` metafunction, which generates a
facilitates interoperability with runtime string processing routines. null-terminated character array that facilitates interoperability with runtime string
processing routines.
__ `Random Access Sequence`_ __ `Bidirectional Sequence`_
__ `Extensible Sequence`_ __ `Extensible Sequence`_
Header Header
@@ -35,12 +36,11 @@ Model of
* |Integral Sequence Wrapper| * |Integral Sequence Wrapper|
* |Variadic Sequence| * |Variadic Sequence|
* |Random Access Sequence| * |Bidirectional Sequence|
* |Extensible Sequence| * |Extensible Sequence|
* |Back Extensible Sequence| * |Back Extensible Sequence|
* |Front Extensible Sequence| * |Front Extensible Sequence|
Expression semantics Expression semantics
-------------------- --------------------
@@ -60,24 +60,21 @@ and |c1...cn| are arbitrary (multi-)characters.
| string<|c1...cn|>::type | | | string<|c1...cn|>::type | |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
| ``begin<s>::type`` | An iterator pointing to the beginning of ``s``; | | ``begin<s>::type`` | An iterator pointing to the beginning of ``s``; |
| | see |Random Access Sequence|. | | | see |Bidirectional Sequence|. |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
| ``end<s>::type`` | An iterator pointing to the end of ``s``; | | ``end<s>::type`` | An iterator pointing to the end of ``s``; |
| | see |Random Access Sequence|. | | | see |Bidirectional Sequence|. |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
| ``size<s>::type`` | The size of ``s``; see |Random Access Sequence|. | | ``size<s>::type`` | The size of ``s``; see |Bidirectional Sequence|. |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
| ``empty<s>::type`` | |true if and only if| the sequence is empty; | | ``empty<s>::type`` | |true if and only if| the sequence is empty; |
| | see |Random Access Sequence|. | | | see |Bidirectional Sequence|. |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
| ``front<s>::type`` | The first element in ``s``; see | | ``front<s>::type`` | The first element in ``s``; see |
| | |Random Access Sequence|. | | | |Bidirectional Sequence|. |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
| ``back<s>::type`` | The last element in ``s``; see | | ``back<s>::type`` | The last element in ``s``; see |
| | |Random Access Sequence|. | | | |Bidirectional Sequence|. |
+---------------------------------------+-----------------------------------------------------------+
| ``at<s,n>::type`` | The ``n``\ th element from the beginning of ``s``; see |
| | |Random Access Sequence|. |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
| ``insert<s,pos,x>::type`` | A new ``string`` of following elements: | | ``insert<s,pos,x>::type`` | A new ``string`` of following elements: |
| | [``begin<s>::type``, ``pos``), ``x``, | | | [``begin<s>::type``, ``pos``), ``x``, |
@@ -114,11 +111,10 @@ and |c1...cn| are arbitrary (multi-)characters.
| | [``next< begin<s>::type >::type``, ``end<s>::type``); | | | [``next< begin<s>::type >::type``, ``end<s>::type``); |
| | see |Front Extensible Sequence|. | | | see |Front Extensible Sequence|. |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
| ``s::c_str`` | A null-terminated byte string such that | | ``c_str<s>::value`` | A null-terminated byte string such that |
| | ``s::c_str[``\ *n*\ ``]`` is | | | ``c_str<s>::value[``\ *n*\ ``]`` is equal to the *n*\ -th |
| | ``at<s,``\ *n*\ ``>::type::value`` for each *n* in | | | character in ``s``, and |
| | [``0``, ``size<s>::type::value``), and | | | ``c_str<s>::value[size<s>::type::value]`` is ``'\0'``. |
| | ``s::c_str[size<s>::type::value]`` is ``'\0'``. |
+---------------------------------------+-----------------------------------------------------------+ +---------------------------------------+-----------------------------------------------------------+
@@ -127,14 +123,13 @@ Example
.. parsed-literal:: .. parsed-literal::
typedef string<'hell','o wo','rld'> hello; typedef mpl::string<'hell','o wo','rld'> hello;
typedef push_back<hello, char_<'!'> >::type hello2; typedef mpl::push_back<hello, mpl::char_<'!'> >::type hello2;
BOOST_ASSERT(0 == std::strcmp(hello2::c_str, "hello world!")); BOOST_ASSERT(0 == std::strcmp(mpl::c_str<hello2>::value, "hello world!"));
See also 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|

View File

@@ -14,23 +14,21 @@
// $Date: 2009-04-01 02:10:26 -0700 (Wed, 1 Apr 2009) $ // $Date: 2009-04-01 02:10:26 -0700 (Wed, 1 Apr 2009) $
// $Revision: 49239 $ // $Revision: 49239 $
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/char.hpp> #include <boost/mpl/char.hpp>
#include <boost/mpl/long.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/copy.hpp> #include <boost/mpl/copy.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/assert.hpp> #include <boost/mpl/assert.hpp>
#include <boost/mpl/size_t.hpp> #include <boost/mpl/size_t.hpp>
#include <boost/mpl/joint_view.hpp> #include <boost/mpl/joint_view.hpp>
#include <boost/mpl/insert_range.hpp> #include <boost/mpl/insert_range.hpp>
#include <boost/mpl/back_inserter.hpp> #include <boost/mpl/back_inserter.hpp>
#include <boost/mpl/front_inserter.hpp>
#include <boost/mpl/iterator_range.hpp> #include <boost/mpl/iterator_range.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp> #include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/arithmetic/add.hpp> #include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/arithmetic/div.hpp> #include <boost/preprocessor/arithmetic/div.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp> #include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp> #include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp> #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
@@ -51,10 +49,10 @@ namespace boost { namespace mpl
struct string_tag; struct string_tag;
struct string_iterator_tag; struct string_iterator_tag;
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C, 0)> template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_STRING_MAX_PARAMS, unsigned C, 0)>
struct string; struct string;
template<typename Sequence, unsigned long N> template<typename Sequence, unsigned I, unsigned J>
struct string_iterator; struct string_iterator;
template<typename Sequence> template<typename Sequence>
@@ -64,36 +62,40 @@ namespace boost { namespace mpl
struct size_impl; struct size_impl;
template<> template<>
struct size_impl<string_tag> struct size_impl<mpl::string_tag>
{ {
template<typename Sequence> template<typename Sequence>
struct apply struct apply;
: mpl::size_t<Sequence::size>
{};
};
template<typename Tag> #define M0(z, n, data) \
struct at_impl; + BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C,n))
#define M1(z, n, data) \
template<BOOST_PP_ENUM_PARAMS_Z(z, n, unsigned C)> \
struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
: 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<> template<>
struct at_impl<string_tag> struct size_impl<mpl::string_tag>::apply<mpl::string<> >
{ : mpl::size_t<0>
template<typename Sequence, typename N> {};
struct apply
: Sequence::template at<N::value>
{};
};
template<typename Tag> template<typename Tag>
struct begin_impl; struct begin_impl;
template<> template<>
struct begin_impl<string_tag> struct begin_impl<mpl::string_tag>
{ {
template<typename Sequence> template<typename Sequence>
struct apply struct apply
{ {
typedef string_iterator<Sequence, 0> type; typedef mpl::string_iterator<Sequence, 0, 0> type;
}; };
}; };
@@ -101,102 +103,212 @@ namespace boost { namespace mpl
struct end_impl; struct end_impl;
template<> template<>
struct end_impl<string_tag> struct end_impl<mpl::string_tag>
{ {
template<typename Sequence> template<typename Sequence>
struct apply struct apply;
{
typedef string_iterator<Sequence, Sequence::size> type; #define M0(z,n,data) \
template<BOOST_PP_ENUM_PARAMS_Z(z, n, unsigned C)> \
struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
{ \
typedef mpl::string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, n, 0> type; \
}; };
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
#undef M0
};
template<>
struct end_impl<mpl::string_tag>::apply<mpl::string<> >
{
typedef mpl::string_iterator<mpl::string<>, 0, 0> type;
}; };
template<typename Tag> template<typename Tag>
struct push_back_impl; struct push_back_impl;
template<> template<>
struct push_back_impl<string_tag> struct push_back_impl<mpl::string_tag>
{ {
template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::back_))> template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::back_))>
struct apply struct apply
{ {
BOOST_MPL_ASSERT_MSG(false, PUSH_BACK_FAILED_MPL_STRING_IS_FULL, (Sequence)); BOOST_MPL_ASSERT_MSG(
typedef void type; (BOOST_MPL_STRING_MAX_LENGTH != mpl::size<Sequence>::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<mpl::string<> >
>::type
, Value
>::type
type;
}; };
template<typename Value> template<typename Value>
struct apply<string<>, Value, false> struct apply<mpl::string<>, Value, false>
{ {
typedef string<(char)Value::value> type; typedef mpl::string<(char)Value::value> type;
}; };
#define M0(z,n,data) \ #define M0(z,n,data) \
template<BOOST_PP_ENUM_PARAMS_Z(z, n, unsigned int C), typename Value> \ template<BOOST_PP_ENUM_PARAMS_Z(z, n, unsigned C), typename Value> \
struct apply<string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, false> \ struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, false> \
{ \ { \
typedef string< \ typedef \
BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \ mpl::string< \
BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \
(BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \ BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \
?BOOST_PP_CAT(C,BOOST_PP_DEC(n)) \ (BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \
:(BOOST_PP_CAT(C,BOOST_PP_DEC(n))<<8)|(unsigned char)Value::value \ ?BOOST_PP_CAT(C,BOOST_PP_DEC(n)) \
, (BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \ :(BOOST_PP_CAT(C,BOOST_PP_DEC(n))<<8)|(unsigned char)Value::value \
?(char)Value::value \ , (BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \
:0 \ ?(char)Value::value \
> type; \ :0 \
> \
type; \
}; };
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
#undef M0 #undef M0
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C), typename Value> template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned C), typename Value>
struct apply<string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false> struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false>
{ {
typedef string< typedef
BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), C) mpl::string<
, (BOOST_PP_CAT(C,BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS))<<8)|(unsigned char)Value::value BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), C)
> type; , (BOOST_PP_CAT(C,BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS))<<8)|(unsigned char)Value::value
>
type;
}; };
}; };
template<typename Tag>
struct pop_back_impl;
template<>
struct pop_back_impl<mpl::string_tag>
{
template<typename Sequence>
struct apply;
#define M0(z,n,data) \
template<BOOST_PP_ENUM_PARAMS_Z(z, n, unsigned C)> \
struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
{ \
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<typename Tag> template<typename Tag>
struct push_front_impl; struct push_front_impl;
template<> template<>
struct push_front_impl<string_tag> struct push_front_impl<mpl::string_tag>
{ {
template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))> template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))>
struct apply struct apply
{ {
BOOST_MPL_ASSERT_MSG(false, PUSH_FRONT_FAILED_MPL_STRING_IS_FULL, (Sequence)); BOOST_MPL_ASSERT_MSG(
typedef void type; (BOOST_MPL_STRING_MAX_LENGTH != mpl::size<Sequence>::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<string<> >
>::type
, Value
>::type
type;
}; };
template<typename Value> template<typename Value>
struct apply<string<>, Value, false> struct apply<mpl::string<>, Value, false>
{ {
typedef string<(char)Value::value> type; typedef mpl::string<(char)Value::value> type;
}; };
#define M0(z,n,data) \ #define M0(z,n,data) \
template<BOOST_PP_ENUM_PARAMS_Z(z, n, unsigned int C), typename Value> \ template<BOOST_PP_ENUM_PARAMS_Z(z, n, unsigned C), typename Value> \
struct apply<string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, true> \ struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, true> \
{ \ { \
typedef string< \ typedef \
(char)Value::value \ mpl::string< \
BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, C) \ (char)Value::value \
> type; \ 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, ~) BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
#undef M0 #undef M0
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C), typename Value> template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned C), typename Value>
struct apply<string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false> struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false>
{ {
typedef string< typedef
((((unsigned char)Value::value)<<(BOOST_MPL_MULTICHAR_LENGTH(C0)*8))|C0) mpl::string<
, BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C) ((((unsigned char)Value::value)<<(BOOST_MPL_MULTICHAR_LENGTH(C0)*8))|C0)
> type; , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)
>
type;
};
};
template<typename Tag>
struct pop_front_impl;
template<>
struct pop_front_impl<mpl::string_tag>
{
template<typename Sequence, bool B = (1==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))>
struct apply;
#define M0(z,n,data) \
template<BOOST_PP_ENUM_PARAMS_Z(z, n, unsigned C)> \
struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, true> \
{ \
BOOST_MPL_ASSERT_MSG((C0 != 0), POP_FRONT_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \
typedef \
mpl::string<BOOST_PP_ENUM_SHIFTED_PARAMS_Z(z, n, C)> \
type; \
};
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
#undef M0
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned C)>
struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, 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; struct insert_range_impl;
template<> template<>
struct insert_range_impl<string_tag> struct insert_range_impl<mpl::string_tag>
{ {
template<typename Sequence, typename Pos, typename Range> template<typename Sequence, typename Pos, typename Range>
struct apply struct apply
: copy< : mpl::copy<
joint_view< mpl::joint_view<
iterator_range< mpl::iterator_range<
string_iterator<Sequence, 0> mpl::string_iterator<Sequence, 0, 0>
, Pos , Pos
> >
, joint_view< , mpl::joint_view<
Range Range
, iterator_range< , mpl::iterator_range<
Pos Pos
, string_iterator<Sequence, Sequence::size> , typename mpl::end<Sequence>::type
> >
> >
> >
, back_inserter<string<> > , mpl::back_inserter<mpl::string<> >
> >
{}; {};
}; };
@@ -231,11 +343,11 @@ namespace boost { namespace mpl
struct insert_impl; struct insert_impl;
template<> template<>
struct insert_impl<string_tag> struct insert_impl<mpl::string_tag>
{ {
template<typename Sequence, typename Pos, typename Value> template<typename Sequence, typename Pos, typename Value>
struct apply struct apply
: insert_range<Sequence, Pos, string<(char)Value::value> > : mpl::insert_range<Sequence, Pos, mpl::string<(char)Value::value> >
{}; {};
}; };
@@ -243,22 +355,22 @@ namespace boost { namespace mpl
struct erase_impl; struct erase_impl;
template<> template<>
struct erase_impl<string_tag> struct erase_impl<mpl::string_tag>
{ {
template<typename Sequence, typename First, typename Last> template<typename Sequence, typename First, typename Last>
struct apply struct apply
: copy< : mpl::copy<
joint_view< mpl::joint_view<
iterator_range< mpl::iterator_range<
string_iterator<Sequence, 0> mpl::string_iterator<Sequence, 0, 0>
, First , First
> >
, iterator_range< , mpl::iterator_range<
typename if_na<Last, typename next<First>::type>::type typename mpl::if_na<Last, typename mpl::next<First>::type>::type
, string_iterator<Sequence, Sequence::size> , typename mpl::end<Sequence>::type
> >
> >
, back_inserter<string<> > , mpl::back_inserter<mpl::string<> >
> >
{}; {};
}; };
@@ -267,152 +379,122 @@ namespace boost { namespace mpl
struct clear_impl; struct clear_impl;
template<> template<>
struct clear_impl<string_tag> struct clear_impl<mpl::string_tag>
{ {
template<typename> template<typename>
struct apply struct apply
{ {
typedef string<> type; typedef mpl::string<> type;
}; };
}; };
template<typename Tag> #define M0(z, n, data) \
struct advance_impl; template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned C), unsigned J> \
struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, J> \
template<> { \
struct advance_impl<string_iterator_tag> typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string; \
{ typedef std::bidirectional_iterator_tag category; \
template<typename Iterator, typename N> typedef \
struct apply typename mpl::if_c< \
{ (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == J + 1) \
typedef string_iterator< , mpl::string_iterator<string, n + 1, 0> \
typename Iterator::string_type , mpl::string_iterator<string, n, J + 1> \
, Iterator::index + N::value >::type \
> type; next; \
}; typedef \
mpl::string_iterator<string, n, J-1> \
prior; \
typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), J)> type; \
}; \
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned C)> \
struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, 0> \
{ \
typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> 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<string, n + 1, 0> \
, mpl::string_iterator<string, n, 1> \
>::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_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), 0)> type; \
}; };
template<typename Tag> BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
struct distance_impl; #undef M0
template<> template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned C)>
struct distance_impl<string_iterator_tag>
{
template<typename First, typename Last>
struct apply
{
typedef mpl::long_<(long)Last::index - (long)First::index> type;
};
};
template<typename Sequence, unsigned long N>
struct string_iterator
: Sequence::template at<N>
{
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<Sequence, N+1> next;
typedef string_iterator<Sequence, N-1> prior;
};
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C)>
struct string struct string
{ {
/// INTERNAL ONLY /// INTERNAL ONLY
static unsigned int const front_ = C0; enum
/// INTERNAL ONLY {
static unsigned int const back_ = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)); front_ = C0
/// INTERNAL ONLY , back_ = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS))
typedef string<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> rest_; };
typedef string type; typedef string type;
typedef string_tag tag;
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<unsigned long Pos, bool B>
struct at_impl
: boost::mpl::char_<BOOST_MPL_MULTICHAR_AT(C0,Pos)>
{};
/// INTERNAL ONLY
template<unsigned long Pos>
struct at_impl<Pos, false>
: rest_::template at<Pos-BOOST_MPL_MULTICHAR_LENGTH(C0)>
{};
public:
template<unsigned long Pos>
struct at
: at_impl<Pos, (Pos < BOOST_MPL_MULTICHAR_LENGTH(C0))>
{};
#else
template<unsigned long Pos, bool B = (Pos < BOOST_MPL_MULTICHAR_LENGTH(C0))>
struct at
: boost::mpl::char_<BOOST_MPL_MULTICHAR_AT(C0,Pos)>
{};
template<unsigned long Pos>
struct at<Pos, false>
: rest_::template at<Pos-BOOST_MPL_MULTICHAR_LENGTH(C0)>
{};
#endif
static char const c_str[];
}; };
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C)> namespace aux_
char const string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>::c_str[] =
{ {
#define M0(z, n, data) at<n>::value template<typename It, typename End>
BOOST_PP_ENUM(BOOST_MPL_STRING_MAX_LENGTH, M0, ~) struct next_unless
#undef M0 : mpl::next<It>
, '\0' // to ensure the string is null-terminated
};
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C)>
std::size_t const string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>::size;
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C)>
unsigned int const string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>::front_;
template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C)>
unsigned int const string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>::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<unsigned long>
struct at
: boost::mpl::char_<'\0'>
{}; {};
static char const c_str[]; template<typename End>
struct next_unless<End, End>
{
typedef End type;
};
template<typename It, typename End>
struct deref_unless
: mpl::deref<It>
{};
template<typename End>
struct deref_unless<End, End>
{
typedef mpl::char_<'\0'> type;
};
}
template<typename Sequence>
struct c_str
{
typedef typename mpl::end<Sequence>::type iend;
typedef typename mpl::begin<Sequence>::type i0;
#define M0(z, n, data) \
typedef \
typename mpl::aux_::next_unless<BOOST_PP_CAT(i, n), iend>::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'}; template<typename Sequence>
std::size_t const string<>::size; char const c_str<Sequence>::value[] =
unsigned int const string<>::front_; {
unsigned int const string<>::back_; #define M0(z, n, data) \
mpl::aux_::deref_unless<BOOST_PP_CAT(i, n), iend>::type::value,
BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_LENGTH, M0, ~)
#undef M0
'\0'
};
}} // namespace boost }} // namespace boost

View File

@@ -17,27 +17,21 @@
#include <boost/mpl/string.hpp> #include <boost/mpl/string.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/long.hpp>
#include <boost/mpl/back.hpp> #include <boost/mpl/back.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/empty.hpp> #include <boost/mpl/empty.hpp>
#include <boost/mpl/front.hpp> #include <boost/mpl/front.hpp>
#include <boost/mpl/clear.hpp>
#include <boost/mpl/erase.hpp> #include <boost/mpl/erase.hpp>
#include <boost/mpl/insert.hpp> #include <boost/mpl/insert.hpp>
#include <boost/mpl/assert.hpp> #include <boost/mpl/advance.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/for_each.hpp> #include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector_c.hpp> #include <boost/mpl/vector_c.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/push_back.hpp> #include <boost/mpl/push_back.hpp>
#include <boost/mpl/joint_view.hpp> #include <boost/mpl/push_front.hpp>
#include <boost/mpl/insert_range.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <boost/mpl/iterator_range.hpp>
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
namespace mpl = boost::mpl; namespace mpl = boost::mpl;
// Accept a string as a template parameter! // Accept a string as a template parameter!
@@ -64,18 +58,287 @@ struct push_char
std::string *str_; std::string *str_;
}; };
void test1() int main()
{ {
BOOST_TEST(0 == std::strcmp(mpl::string<'Hell','o wo','rld!'>::c_str, "Hello world!")); // Test mpl::size of strings
BOOST_TEST((12 == mpl::size<mpl::string<'Hell','o wo','rld!'> >::type::value)); {
BOOST_TEST(('w' == mpl::at_c<mpl::string<'Hell','o wo','rld!'>, 6>::type::value)); 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<mpl::string<> >::value));
BOOST_MPL_ASSERT_RELATION(1, ==, (mpl::size<mpl::string<'a'> >::value));
BOOST_MPL_ASSERT_RELATION(2, ==, (mpl::size<mpl::string<'ab'> >::value));
BOOST_MPL_ASSERT_RELATION(2, ==, (mpl::size<mpl::string<'a','b'> >::value));
BOOST_MPL_ASSERT_RELATION(4, ==, (mpl::size<mpl::string<'abcd'> >::value));
BOOST_MPL_ASSERT_RELATION(5, ==, (mpl::size<mpl::string<'abcd','e'> >::value));
BOOST_MPL_ASSERT_RELATION(31, ==, (mpl::size<almost_full>::value));
BOOST_MPL_ASSERT_RELATION(32, ==, (mpl::size<full>::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<mpl::string<> >::type
, mpl::end<mpl::string<> >::type
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::begin<mpl::string<'a'> >::type
, mpl::string_iterator<mpl::string<'a'>, 0, 0>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::end<mpl::string<'a'> >::type
, mpl::string_iterator<mpl::string<'a'>, 1, 0>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::begin<almost_full>::type
, mpl::string_iterator<almost_full, 0, 0>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::end<almost_full>::type
, mpl::string_iterator<almost_full, 8, 0>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::begin<full>::type
, mpl::string_iterator<full, 0, 0>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::end<full>::type
, mpl::string_iterator<full, 8, 0>
>
));
}
// testing push_back
{
typedef mpl::push_back<mpl::string<>, mpl::char_<'a'> >::type t1;
BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));
typedef mpl::push_back<t1, mpl::char_<'b'> >::type t2;
BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ab'> >));
typedef mpl::push_back<t2, mpl::char_<'c'> >::type t3;
BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'abc'> >));
typedef mpl::push_back<t3, mpl::char_<'d'> >::type t4;
BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'abcd'> >));
typedef mpl::push_back<t4, mpl::char_<'e'> >::type t5;
BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'abcd','e'> >));
typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
typedef mpl::push_back<almost_full, mpl::char_<'X'> >::type t6;
BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >));
}
// Test mpl::next
{
typedef mpl::string<'a','bc','def','ghij'> s;
typedef mpl::begin<s>::type i0;
BOOST_MPL_ASSERT((boost::is_same<i0, mpl::string_iterator<s,0,0> >));
typedef mpl::next<i0>::type i1;
BOOST_MPL_ASSERT((boost::is_same<i1, mpl::string_iterator<s,1,0> >));
typedef mpl::next<i1>::type i2;
BOOST_MPL_ASSERT((boost::is_same<i2, mpl::string_iterator<s,1,1> >));
typedef mpl::next<i2>::type i3;
BOOST_MPL_ASSERT((boost::is_same<i3, mpl::string_iterator<s,2,0> >));
typedef mpl::next<i3>::type i4;
BOOST_MPL_ASSERT((boost::is_same<i4, mpl::string_iterator<s,2,1> >));
typedef mpl::next<i4>::type i5;
BOOST_MPL_ASSERT((boost::is_same<i5, mpl::string_iterator<s,2,2> >));
typedef mpl::next<i5>::type i6;
BOOST_MPL_ASSERT((boost::is_same<i6, mpl::string_iterator<s,3,0> >));
typedef mpl::next<i6>::type i7;
BOOST_MPL_ASSERT((boost::is_same<i7, mpl::string_iterator<s,3,1> >));
typedef mpl::next<i7>::type i8;
BOOST_MPL_ASSERT((boost::is_same<i8, mpl::string_iterator<s,3,2> >));
typedef mpl::next<i8>::type i9;
BOOST_MPL_ASSERT((boost::is_same<i9, mpl::string_iterator<s,3,3> >));
typedef mpl::next<i9>::type i10;
BOOST_MPL_ASSERT((boost::is_same<i10, mpl::string_iterator<s,4,0> >));
BOOST_MPL_ASSERT((boost::is_same<i10, mpl::end<s>::type>));
}
// Test mpl::prior
{
typedef mpl::string<'a','bc','def','ghij'> s;
typedef mpl::end<s>::type i10;
BOOST_MPL_ASSERT((boost::is_same<i10, mpl::string_iterator<s,4,0> >));
typedef mpl::prior<i10>::type i9;
BOOST_MPL_ASSERT((boost::is_same<i9, mpl::string_iterator<s,3,3> >));
typedef mpl::prior<i9>::type i8;
BOOST_MPL_ASSERT((boost::is_same<i8, mpl::string_iterator<s,3,2> >));
typedef mpl::prior<i8>::type i7;
BOOST_MPL_ASSERT((boost::is_same<i7, mpl::string_iterator<s,3,1> >));
typedef mpl::prior<i7>::type i6;
BOOST_MPL_ASSERT((boost::is_same<i6, mpl::string_iterator<s,3,0> >));
typedef mpl::prior<i6>::type i5;
BOOST_MPL_ASSERT((boost::is_same<i5, mpl::string_iterator<s,2,2> >));
typedef mpl::prior<i5>::type i4;
BOOST_MPL_ASSERT((boost::is_same<i4, mpl::string_iterator<s,2,1> >));
typedef mpl::prior<i4>::type i3;
BOOST_MPL_ASSERT((boost::is_same<i3, mpl::string_iterator<s,2,0> >));
typedef mpl::prior<i3>::type i2;
BOOST_MPL_ASSERT((boost::is_same<i2, mpl::string_iterator<s,1,1> >));
typedef mpl::prior<i2>::type i1;
BOOST_MPL_ASSERT((boost::is_same<i1, mpl::string_iterator<s,1,0> >));
typedef mpl::prior<i1>::type i0;
BOOST_MPL_ASSERT((boost::is_same<i0, mpl::string_iterator<s,0,0> >));
BOOST_MPL_ASSERT((boost::is_same<i0, mpl::begin<s>::type>));
}
// Test mpl::deref
{
typedef mpl::string<'a','bc','def','ghij'> s;
typedef mpl::begin<s>::type i0;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i0>::type, mpl::char_<'a'> >));
typedef mpl::next<i0>::type i1;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i1>::type, mpl::char_<'b'> >));
typedef mpl::next<i1>::type i2;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i2>::type, mpl::char_<'c'> >));
typedef mpl::next<i2>::type i3;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i3>::type, mpl::char_<'d'> >));
typedef mpl::next<i3>::type i4;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i4>::type, mpl::char_<'e'> >));
typedef mpl::next<i4>::type i5;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i5>::type, mpl::char_<'f'> >));
typedef mpl::next<i5>::type i6;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i6>::type, mpl::char_<'g'> >));
typedef mpl::next<i6>::type i7;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i7>::type, mpl::char_<'h'> >));
typedef mpl::next<i7>::type i8;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i8>::type, mpl::char_<'i'> >));
typedef mpl::next<i8>::type i9;
BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i9>::type, mpl::char_<'j'> >));
}
// testing push_back
{
typedef mpl::push_back<mpl::string<>, mpl::char_<'a'> >::type t1;
BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));
typedef mpl::push_back<t1, mpl::char_<'b'> >::type t2;
BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ab'> >));
typedef mpl::push_back<t2, mpl::char_<'c'> >::type t3;
BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'abc'> >));
typedef mpl::push_back<t3, mpl::char_<'d'> >::type t4;
BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'abcd'> >));
typedef mpl::push_back<t4, mpl::char_<'e'> >::type t5;
BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'abcd','e'> >));
typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
typedef mpl::push_back<almost_full, mpl::char_<'X'> >::type t6;
BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >));
typedef mpl::string<'a','a','a','a','a','a','a','aaaa'> must_repack;
typedef mpl::push_back<must_repack, mpl::char_<'X'> >::type t7;
BOOST_MPL_ASSERT((boost::is_same<t7, mpl::string<'aaaa','aaaa','aaaX'> >));
}
// testing push_front
{
typedef mpl::push_front<mpl::string<>, mpl::char_<'a'> >::type t1;
BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));
typedef mpl::push_front<t1, mpl::char_<'b'> >::type t2;
BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ba'> >));
typedef mpl::push_front<t2, mpl::char_<'c'> >::type t3;
BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'cba'> >));
typedef mpl::push_front<t3, mpl::char_<'d'> >::type t4;
BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'dcba'> >));
typedef mpl::push_front<t4, mpl::char_<'e'> >::type t5;
BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'e','dcba'> >));
typedef mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> almost_full;
typedef mpl::push_front<almost_full, mpl::char_<'X'> >::type t6;
BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'Xaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >));
typedef mpl::string<'aaaa','a','a','a','a','a','a','a'> must_repack;
typedef mpl::push_front<must_repack, mpl::char_<'X'> >::type t7;
BOOST_MPL_ASSERT((boost::is_same<t7, mpl::string<'Xaaa','aaaa','aaaa'> >));
}
// Test c_str<>
BOOST_TEST(0 == std::strcmp(
mpl::c_str<mpl::string<> >::value
, ""
));
BOOST_TEST(0 == std::strcmp(
mpl::c_str<mpl::string<'Hell','o wo','rld!'> >::value
, "Hell" "o wo" "rld!"
));
BOOST_TEST(0 == std::strcmp(
mpl::c_str<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >::value
, "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaX"
));
// test using a string as a template parameter // test using a string as a template parameter
greeting<mpl::string<'Hell','o wo','rld!'>::c_str> g; greeting<mpl::c_str<mpl::string<'Hell','o wo','rld!'> >::value> g;
BOOST_TEST("Hello world!" == g.say_hello()); BOOST_TEST("Hello world!" == g.say_hello());
BOOST_TEST(0 == std::strcmp("", mpl::string<>::c_str));
std::string result; std::string result;
mpl::for_each<mpl::string<'Hell','o wo','rld!'> >(push_char(result)); mpl::for_each<mpl::string<'Hell','o wo','rld!'> >(push_char(result));
BOOST_TEST("Hello world!" == result); BOOST_TEST("Hello world!" == result);
@@ -85,89 +348,128 @@ void test1()
BOOST_TEST(('h' == mpl::front<mpl::string<'hi!'> >::type())); BOOST_TEST(('h' == mpl::front<mpl::string<'hi!'> >::type()));
BOOST_TEST(('!' == mpl::back<mpl::string<'hi!'> >::type())); BOOST_TEST(('!' == mpl::back<mpl::string<'hi!'> >::type()));
}
// testing push_back
void test2()
{
typedef mpl::push_back<mpl::string<>, mpl::char_<'a'> >::type t1;
BOOST_TEST(0 == std::strcmp("a", t1::c_str));
typedef mpl::push_back<t1, mpl::char_<'b'> >::type t2;
BOOST_TEST(0 == std::strcmp("ab", t2::c_str));
typedef mpl::push_back<t2, mpl::char_<'c'> >::type t3;
BOOST_TEST(0 == std::strcmp("abc", t3::c_str));
BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'abc'> >));
typedef mpl::push_back<t3, mpl::char_<'d'> >::type t4;
BOOST_TEST(0 == std::strcmp("abcd", t4::c_str));
typedef mpl::push_back<t4, mpl::char_<'e'> >::type t5;
BOOST_TEST(0 == std::strcmp("abcde", t5::c_str));
BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'abcd','e'> >));
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<almost_full, mpl::char_<'X'> >::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::string<>, mpl::char_<'a'> >::type t1;
BOOST_TEST(0 == std::strcmp("a", t1::c_str));
typedef mpl::push_front<t1, mpl::char_<'b'> >::type t2;
BOOST_TEST(0 == std::strcmp("ba", t2::c_str));
typedef mpl::push_front<t2, mpl::char_<'c'> >::type t3;
BOOST_TEST(0 == std::strcmp("cba", t3::c_str));
typedef mpl::push_front<t3, mpl::char_<'d'> >::type t4;
BOOST_TEST(0 == std::strcmp("dcba", t4::c_str));
typedef mpl::push_front<t4, mpl::char_<'e'> >::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<almost_full, mpl::char_<'X'> >::type t6;
BOOST_TEST(0 == std::strcmp("Xaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa", t6::c_str));
}
void test4()
{
// back-inserter with copy // back-inserter with copy
typedef mpl::vector_c<char, 'a','b','c','d','e'> rgc; typedef mpl::vector_c<char, 'a','b','c','d','e'> rgc;
BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<rgc>::value));
typedef mpl::copy<rgc, mpl::back_inserter<mpl::string<> > >::type str; typedef mpl::copy<rgc, mpl::back_inserter<mpl::string<> > >::type str;
BOOST_TEST(0 == std::strcmp("abcde", str::c_str)); BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<str>::value));
}
// test insert_range and erase // test insert_range and erase
void test5() {
{ typedef mpl::string<'Hell','o wo','rld!'> hello;
typedef mpl::string<'Hell','o wo','rld!'> hello; typedef mpl::advance_c<mpl::begin<hello>::type, 5>::type where;
typedef mpl::advance_c<mpl::begin<hello>::type, 5>::type where; typedef mpl::string<' cru','el'> cruel;
typedef mpl::string<' cru','el'> cruel; typedef mpl::insert_range<hello, where, cruel>::type hello_cruel;
typedef mpl::insert_range<hello, where, cruel>::type hello_cruel; BOOST_TEST(0 == std::strcmp("Hello cruel world!", mpl::c_str<hello_cruel>::value));
BOOST_TEST(0 == std::strcmp("Hello cruel world!", hello_cruel::c_str));
typedef mpl::erase<hello, mpl::begin<hello>::type, where>::type erased1; typedef mpl::erase<hello, mpl::begin<hello>::type, where>::type erased1;
BOOST_TEST(0 == std::strcmp(" world!", erased1::c_str)); BOOST_TEST(0 == std::strcmp(" world!", mpl::c_str<erased1>::value));
} }
// test pop_front
{
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_front<mpl::string<'a'> >::type
, mpl::string<>
>
));
int main() BOOST_MPL_ASSERT((
{ boost::is_same<
test1(); mpl::pop_front<mpl::string<'ab'> >::type
test2(); , mpl::string<'b'>
test3(); >
test4(); ));
test5();
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_front<mpl::string<'abc'> >::type
, mpl::string<'bc'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_front<mpl::string<'abcd'> >::type
, mpl::string<'bcd'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_front<mpl::string<'abcd','e'> >::type
, mpl::string<'bcd','e'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_front<mpl::string<'d','e'> >::type
, mpl::string<'e'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_front<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >::type
, mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'>
>
));
}
// test pop_back
{
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_back<mpl::string<'a'> >::type
, mpl::string<>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_back<mpl::string<'ab'> >::type
, mpl::string<'a'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_back<mpl::string<'abc'> >::type
, mpl::string<'ab'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_back<mpl::string<'abcd'> >::type
, mpl::string<'abc'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_back<mpl::string<'abcd','e'> >::type
, mpl::string<'abcd'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_back<mpl::string<'d','e'> >::type
, mpl::string<'d'>
>
));
BOOST_MPL_ASSERT((
boost::is_same<
mpl::pop_back<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >::type
, mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'>
>
));
}
return boost::report_errors(); return boost::report_errors();
} }