Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2008-03-20 21:01:11


Matt Hurd wrote:
>> On 20/03/2008, Tom Brinkman <reportbase_at_[hidden]> wrote:
>> >> Why would one bother to do this.
>>
>> Good question. Maybe just because they say that you cant.
> That's almost a good enough reason for me:-)
>
> It was raised with a mpl vector snippet in April 2005:
> http://article.gmane.org/gmane.comp.lib.boost.devel/121612
>
> I think it is useful as then you can do all sorts of compile time
> string / packet manipulation for parsing, offset calculations and take
> a whole bunch of run time calcs out of the equation with some elegance
> and ease the maintenance burden. Plenty of first, follows compile
> time parsing you can do from a grammar POV. Interesting foo you could
> do for a lexical parser, regex or other kinds of state machine
> optimisation. Perfect hashing for strings at compile time...
>
> The main problem is you can't do this without a pre-processing stage
> elegantly. There is just no way to support a macro or any other
> succinct form of compile time string without a pre-processing stage.
> It is just clumsy.

Here's a slightly goofy way to do it using multi-character character
constants. I'm pretty sure this is non-portable, but it works with gcc
and msvc.

#include <iostream>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/arithmetic/div.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>

#define MAX_CTSTRING_LENGTH 40
#define MAX_CTSTRING_PARAMS BOOST_PP_DIV(MAX_CTSTRING_LENGTH, 4)

#define CTLENGTH(c) \
     ((c&0xff000000)?4:(c&0xff0000)?3:(c&0xff00)?2:1)
#define CTAT(c,i) \
     ((c&(0xff<<((CTLENGTH(c)-i-1)*8)))>>(8*(CTLENGTH(c)-i-1)))

template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(MAX_CTSTRING_PARAMS, int i, 0)>
struct ctstring
{
     template<int I, bool B = (I < CTLENGTH(i0))>
     struct at
     {
         static char const value = CTAT(i0,I);
     };

     template<int I>
     struct at<I, false>
       : ctstring<BOOST_PP_ENUM_SHIFTED_PARAMS(MAX_CTSTRING_PARAMS, i)>
             ::template at<I-CTLENGTH(i0)>
     {};

     static char const value[];
};

template<BOOST_PP_ENUM_PARAMS(MAX_CTSTRING_PARAMS, int i)>
char const ctstring<BOOST_PP_ENUM_PARAMS(MAX_CTSTRING_PARAMS, i)>::value[] =
{
#define M0(z, n, data) at<n>::value
     BOOST_PP_ENUM(MAX_CTSTRING_LENGTH, M0, ~)
#undef M0
};

// Accept a string as a template parameter!
template<char const *sz>
struct greeting
{
     void say_hello() const { std::cout << sz << std::endl; }
};

int main()
{
     greeting<ctstring<'Hell','o wo','rld!'>::value> g;
     g.say_hello();

     return 0;
}

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk