Re: [boost] Passing strings as a template parameter (small utility)

Just use mpl::vector_c<char, ....>. Really, what else is there to do?
Not much. Good Idea. typedef mpl::vector_c<char,'H','e','l','p'> help_t; To pull the string out, I believe that you can do this. std::vector<std::string> help; boost::mpl::for_each<help_t>( boost::bind(&std::vector<std::string>::push_back, &help, _1));
Why would one bother to do this.
Good question. Maybe just because they say that you cant.

On 20/03/2008, Tom Brinkman <reportbase@gmail.com> 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. $AUD 0.02, --Matt. __cts"matthurd@acm.org"

Matt Hurd wrote:
On 20/03/2008, Tom Brinkman <reportbase@gmail.com> 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

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
participants (3)
-
Eric Niebler
-
Matt Hurd
-
Tom Brinkman