Boost logo

Boost Users :

Subject: Re: [Boost-users] [mpl]... is there an mpl::string
From: Tor Brede Vekterli (vekterli_at_[hidden])
Date: 2009-04-17 01:37:11

On Mon, Apr 13, 2009 at 5:45 PM, Noah Roberts <roberts.noah_at_[hidden]> wrote:
> Eric Niebler wrote:
>> Eric Niebler wrote:
>>> Eric Niebler wrote:
>>>> There's another consideration that I've been glossing over. mpl::string
>>>> isn't *really* random access. Since mpl::string<'a','b','c'> designates the
>>>> same character sequence as mpl::string<'abc'>, it takes O(N) template
>>>> instantiations to find the N-th element in the sequence, at least in the
>>>> current implementation. I'd like to fix that, but I don't know how (yet).
>>> Now this is really bothering me. The right thing to do is replace the
>>> current implementation with one in which mpl::string is a front- and
>>> back-extensible bidirectional sequence, and give up with the random access
>>> pretense. :-(
>> I've made this change. mpl::string is no longer random access (it never
>> really was). Also, I've changed c_str to be a separate metafunction that
>> works with any forward sequence.
>> Thanks particularly to Noah Roberts for the good feedback.
> No problem.
> Now someone just needs to make format<> :P

Although a tongue-in-cheek remark, the notion of a compile-time
formatting library somehow appeals to me, if for nothing else for its
sheer absurdity ;)

Due to the limits of preprocessor stringization when dealing with
metaprogramming integers, I suspect it might have its use cases
wherever runtime conversion overhead is best avoided. With mpl::string
it's trivial to create integer-to-string conversion metafunctions, and
it should also not be overly complicated to glue these together into
something bigger if so should desired. I whipped up a quick (and not
very pretty) compile-time _itoa equivalent as a small proof of concept
just for fun (only tested on visual c++ 2008)

#include <iostream>
#include <boost/mpl/string.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/push_back.hpp>

namespace mpl = boost::mpl;

struct itoa_ct
  // radix for _itoa() goes up to 36, but only bother with 16 here
  typedef mpl::vector_c<char
> radix_t;

  template <int Radix, unsigned int Quotient>
  struct radix_convert
    typedef typename mpl::push_back<
        typename radix_convert<Radix, Quotient / Radix>::type
      , mpl::char_<mpl::at_c<radix_t, Quotient % Radix>::type::value>
>::type type;

  template <int Radix>
  struct radix_convert<Radix, 0>
    typedef mpl::string<> type;

  template <int I, int Radix = 10>
  struct apply
    // All bases != 10 consider I as unsigned
    typedef typename radix_convert<
      Radix, static_cast<unsigned int>((Radix == 10 && I < 0) ? -I : I)
>::type converted_t;

    // Prefix with '-' if negative and base 10
    typedef typename mpl::if_<
        mpl::bool_<(Radix == 10 && I < 0)>
      , mpl::push_front<converted_t, mpl::char_<'-'> >
      , mpl::identity<converted_t>
>::type::type type;

int main(int argc, char* argv[])
  std::cout << mpl::c_str<itoa_ct::apply<12345>::type>::value << "\n";
  std::cout << mpl::c_str<itoa_ct::apply<-98765>::type>::value << "\n";
  std::cout << mpl::c_str<itoa_ct::apply<2009, 2>::type>::value << "\n";
  std::cout << mpl::c_str<itoa_ct::apply<0xb0057, 16>::type>::value << "\n";
  std::cout << mpl::c_str<itoa_ct::apply<0xffffffff, 16>::type>::value << "\n";
  return 0;

which outputs, as expected:


I'm swamped with thesis-work until June, so I cannot really do much
else with this for now, but I just wanted to throw it out there. Any
thoughts? :)

Tor Brede Vekterli

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at