
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