|
Boost : |
From: Eric Niebler (eric_at_[hidden])
Date: 2008-03-21 14:33:10
Eric Niebler wrote:
> Matt Hurd wrote:
>> 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.
<snip>
> // 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();
> }
Now that I think about it some more, there's really nothing stopping us
from taking this much farther -- access individual characters, calculate
the length, slice and substr, even search and replace. There's no reason
why ctstring<> can't implement most of the std::string interface at
compile time.
Here's a slightly cleaned up version, in case anybody wants to carry
this forward. A good first step might be to make this a valid Fusion
sequence.
#include <iostream>
#include <boost/mpl/integral_c.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_shifted_params.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#define MAX_CTSTRING_LENGTH 128
#define MAX_CTSTRING_PARAMS BOOST_PP_DIV(MAX_CTSTRING_LENGTH, 4)
#define CTLENGTH(c) ((c>0xffffff)+(c>0xffff)+(c>0xff)+1)
#define CTAT(c,i) (char)((c)>>(8*(CTLENGTH(c)-(i)-1)))
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(MAX_CTSTRING_PARAMS,
unsigned int C, 0)>
struct ctstring
{
static std::size_t const size
= CTLENGTH(C0)
+ ctstring<BOOST_PP_ENUM_SHIFTED_PARAMS(MAX_CTSTRING_PARAMS,
C)>::size;
template<unsigned int I, bool B = (I < CTLENGTH(C0))>
struct at
: boost::mpl::integral_c<char, CTAT(C0,I)>
{};
template<unsigned int I>
struct at<I, false>
: ctstring<BOOST_PP_ENUM_SHIFTED_PARAMS(MAX_CTSTRING_PARAMS, C)>
::template at<I-CTLENGTH(C0)>
{};
static char const c_str[];
};
template<BOOST_PP_ENUM_PARAMS(MAX_CTSTRING_PARAMS, unsigned int C)>
char const ctstring<BOOST_PP_ENUM_PARAMS(MAX_CTSTRING_PARAMS, C)>::c_str[] =
{
#define M0(z, n, data) at<n>::value
BOOST_PP_ENUM(MAX_CTSTRING_LENGTH, M0, ~)
#undef M0
};
template<>
struct ctstring<>
{
static std::size_t const size = 0;
template<unsigned int>
struct at
: boost::mpl::integral_c<char, '\0'>
{};
static char const c_str[];
};
char const ctstring<>::c_str[] = {'\0'};
// Accept a string as a template parameter!
template<char const *sz>
struct greeting
{
void say_hello() const { std::cout << sz << std::endl; }
};
int main()
{
std::cout << ctstring<'Hell','o wo','rld!'>::size << std::endl;
greeting<ctstring<'Hell','o wo','rld!'>::c_str> g;
g.say_hello();
std::cout << ctstring<>::c_str << std::endl;
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