|
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
,'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
> 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:
12345
-98765
11111011001
b0057
ffffffff
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? :)
Regards,
Tor Brede Vekterli
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net