$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [Boost-users] [mpl]... is there an mpl::string
From: Noah Roberts (roberts.noah_at_[hidden])
Date: 2009-04-08 16:33:44
Eric Niebler wrote:
>>>> Andy Stevenson wrote:
>>>>>
>>>>> I recall some discussion of there being an mpl::string
>>>>> template..... Can't see it in the mpl library. Is it elsewhere?
> 
> It has been added to trunk as of revision 52208:
> 
> https://svn.boost.org/trac/boost/changeset/52208
> 
> No doubt the regression tests will reveal portability problems. Once 
> they have been worked out, we can move this to release.
> 
Visual Studio 2005 hates it.  Perhaps I'm not going about it the right 
way?  I simply downloaded string.hpp, char.hpp, and char_fwd.hpp and 
altered the include paths so that they'd work in an individual project.
Then I wrote the following test code:
#include <iostream>
#include "string.hpp"
template < char const* str >
struct test
{
   static void print() { std::cout << str << std::endl; }
};
int main()
{
   typedef boost::mpl::string<'hell', 'o wo', 'rld!'> str;
   std::cout << str::template at<0>::value << std::endl;
   std::cin.get();
}
1>e:\dev_workspace\experimental\scratch\scratch\main.cpp(15) : error 
C2976: 'boost::mpl::string<C0,C1,C2>::at' : too few template arguments
1>        with
1>        [
1>            C0=1751477356,
1>            C1=1864398703,
1>            C2=1919706145
1>        ]
This of course causes problems in c_str.
This code fails for the same reason:
#include <iostream>
#include <boost/type_traits.hpp>
template < typename T >
struct test_inner
{
   template < typename X, bool B = boost::is_same<T,X>::value >
   struct inner
   {
     static bool const value = B;
   };
};
int main()
{
   std::cout << test_inner<int>::template inner<int>::value << std::endl;
   std::cin.get();
}
So, looks like VS can't handle default template arguments in these inner 
templates.  I changed the implementation of at<>:
     template < typename String, long Pos, bool B = (Pos < 
BOOST_MPL_MULTICHAR_LENGTH(String::front_)) >
     struct string_at : 
boost::mpl::char_<BOOST_MPL_MULTICHAR_AT(String::front_,Pos)>
     {
     };
     template < typename String, long Pos >
     struct string_at<String, Pos, false>
       : string_at< typename String::rest_, Pos - 
BOOST_MPL_MULTICHAR_LENGTH(String::front_)>
     {
     };
     template<>
     struct at_impl<string_tag>
     {
         template<typename Sequence, typename N>
         struct apply
           : string_at<Sequence, N::value>
         {};
     };
And implemented c_str[] in terms of string_at<>:
     template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned 
int C)>
     char const string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, 
C)>::c_str[] =
     {
     #define M0(z, n, data) 
string_at<string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS,C)>, 
n>::value
         BOOST_PP_ENUM(BOOST_MPL_STRING_MAX_LENGTH, M0, ~)
     #undef M0
       , '\0' // to ensure the string is null-terminated
     };
This code compiles with changes in VS 2005:
#include <iostream>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
#include "string.hpp"
int main()
{
   typedef boost::mpl::string<'hell', 'o wo', 'rld!'> str;
   std::cout << boost::mpl::at<str, boost::mpl::int_<0> >::value << 
std::endl;
   std::cout << str::c_str << std::endl;
   std::cin.get();
}