[concept check][mpl] (Conditional) Concept checking for functions

I have a variety of user defined function objects that I will need to call. Take the following examples:template<int N1, int N2 = 0> struct Func1{ double operator()(boost::array<double, N1>& x1, boost::array<double, N2>& x2){...}}; template<int N1> struct Func2{ double operator()(boost::array<double, N1>& x){...}}; With a function such as template<int N1, int N2 = 0, class F = boost::function<double (boost::array<double, N1>& x1, boost::array<double, N2>& x2)> class DPP{ void solve(){...... uses F...to be discussed} }; I have a few questions: 1) Is there a relatively easy way to use boost concept check to verify that F follows the first function signature so that I can detect compile time the problem? I can't figure out how to do it from the concept check docs, and they say they are out of date. Usage I want to check in the instantiation of DPP: F f; f(boost::array<double, N1>& x1, boost::array<double, N2>& x2) 2) I want the user to be able to pass in a simplified function type if N2 = 0 I assume that to call the actual function I would have some kind of impl function with partial specialization such as: template<bool use_simplified, int N1, int N2> struct use_f_impl(); template<int N1, int N2> struct use_f_impl<true, N1, N2>{ static double use_f() { STATIC_ASSERT(N2 == 0); F f; boost::array<double, N1> x; return f(x); } }; template<int N1, int N2> struct use_f_impl<false, N1, N2>{ static double use_f() { F f; boost::array<double, N1> x1; boost::array<double, N2> x2; return f(x1, x2); } }; And then in my solve() function I go: double val = use_f<(N2 == 0, N1, N2)>::use_f(); Is this the right idiom, pattern, etc? Do I need to use the struct with a static function since function templates don't have partial specialization? 3) Now what if I want to do a concept check on the F passed into DPP? It has to be conditional on the N2 value now. How would I do this? 4) Lets say that I don't want to force them to use the simplified version of the function signature if they don't want to. Can I automatically detect the signature and put it into a flag integer in the class? i.e. inside of the DPP class: static bool use_simple = IsSimple<F>::value; Then pass in the use_simple value when calling use_f_impl. If so, what would the IsSimple metafunction look like and can concept check help? Thanks, Jesse

Hi, I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere? Regards, Andy

Andy Stevenson wrote:
Hi,
I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
I wrote one once and intended to write docs and tests and integrate it into MPL but never got around to it. You can find it here: http://archives.free.net.ph/message/20080324.060757.9880ea2b.el.html -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric, I would be interested in that too. I already had to code around in a project, to make smth. similar. Would be nice to have it in MPL. Many thanks, Ovanes On Mon, Mar 30, 2009 at 5:58 AM, Eric Niebler <eric@boost-consulting.com>wrote:
Andy Stevenson wrote:
Hi,
I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
I wrote one once and intended to write docs and tests and integrate it into MPL but never got around to it. You can find it here:
http://archives.free.net.ph/message/20080324.060757.9880ea2b.el.html
-- Eric Niebler BoostPro Computing http://www.boostpro.com

Ovanes Markarian wrote:
Eric Niebler wrote:
Andy Stevenson wrote:
I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
I wrote one once and intended to write docs and tests and integrate it into MPL but never got around to it. You can find it here:
http://archives.free.net.ph/message/20080324.060757.9880ea2b.el.html
I would be interested in that too. I already had to code around in a project, to make smth. similar.
Would be nice to have it in MPL. Many thanks,
I polished this up, wrote some docs and tests and submitted a patch. It's up to Aleskey now. https://svn.boost.org/trac/boost/ticket/2905 -- Eric Niebler BoostPro Computing http://www.boostpro.com

Andy Stevenson wrote:
I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
It has been added to trunk as of revision 52208: https://svn.boost.org/trac/boost/changeset/52208 No doubt the regression tests will reveal portability problems. Once they have been worked out, we can move this to release. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Andy Stevenson wrote:
I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
It has been added to trunk as of revision 52208:
https://svn.boost.org/trac/boost/changeset/52208
No doubt the regression tests will reveal portability problems. Once they have been worked out, we can move this to release.
Why is this better than a metafunction c_str< Sequence >? typedef mpl::vector_c<char, 'h', 'e', 'l', 'l', 'o'> str; template < char const* sz > struct x {}; x< c_str<str>::value > test; Is there some reason that's not possible or is prone to problems avoided by mpl::string?

Noah Roberts wrote:
Eric Niebler wrote:
Andy Stevenson wrote:
I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
It has been added to trunk as of revision 52208:
https://svn.boost.org/trac/boost/changeset/52208
No doubt the regression tests will reveal portability problems. Once they have been worked out, we can move this to release.
Why is this better than a metafunction c_str< Sequence >?
typedef mpl::vector_c<char, 'h', 'e', 'l', 'l', 'o'> str;
template < char const* sz > struct x {};
x< c_str<str>::value > test;
Is there some reason that's not possible or is prone to problems avoided by mpl::string?
That is certainly a valid design. It's somewhat subjective, but IMO multi-character literals give a nicer compile-time string interface. Consider: // With mpl::vector_c mpl::vector_c<char, 'h','e','l','l','o',' ','w','o','r','l','d'> // With mpl::string mpl::string<'hell','o wo','rld'> Neither will win a beauty contest, but my preference is strongly for the latter. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Tue, Apr 7, 2009 at 12:21 PM, Eric Niebler <eric@boost-consulting.com> wrote:
multi-character literals give a nicer compile-time string interface. // With mpl::string mpl::string<'hell','o wo','rld'>
Hi Eric, I've been lurking on this thread for a while, and I'm intrigued by "multi-character literals". Beside being new to me, a Google search yields little information on them, beside the fact that "The value of a narrow or wide character literal containing more than one character or escape sequence is implementation-defined." Isn't this a problem for mpl::string? Thanks, --DD [1] http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=/com... [2] http://bytes.com/groups/c/739845-multi-character-constant

Dominique Devienne wrote:
On Tue, Apr 7, 2009 at 12:21 PM, Eric Niebler <eric@boost-consulting.com> wrote:
multi-character literals give a nicer compile-time string interface. // With mpl::string mpl::string<'hell','o wo','rld'>
Hi Eric,
I've been lurking on this thread for a while, and I'm intrigued by "multi-character literals". Beside being new to me, a Google search yields little information on them, beside the fact that "The value of a narrow or wide character literal containing more than one character or escape sequence is implementation-defined." Isn't this a problem for mpl::string? Thanks, --DD
"Implementation-defined" means that each compiler vendor is required to document how multi-character literals are assigned integral values. A library like MPL can use this information to provide a specialized implementation for each compiler, presenting the user with a uniform interface. And as it turns out, there is very little variation among compiler vendors around the handling of multi-character literals. So far, just one implementation has sufficed. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Noah Roberts wrote:
Eric Niebler wrote:
Andy Stevenson wrote: > > I recall some discussion of there being an mpl::string > template..... Can't see it in the mpl library. Is it elsewhere?
It has been added to trunk as of revision 52208:
https://svn.boost.org/trac/boost/changeset/52208
No doubt the regression tests will reveal portability problems. Once they have been worked out, we can move this to release.
Why is this better than a metafunction c_str< Sequence >?
typedef mpl::vector_c<char, 'h', 'e', 'l', 'l', 'o'> str;
template < char const* sz > struct x {};
x< c_str<str>::value > test;
Is there some reason that's not possible or is prone to problems avoided by mpl::string?
That is certainly a valid design. It's somewhat subjective, but IMO multi-character literals give a nicer compile-time string interface. Consider:
// With mpl::vector_c mpl::vector_c<char, 'h','e','l','l','o',' ','w','o','r','l','d'>
// With mpl::string mpl::string<'hell','o wo','rld'>
Neither will win a beauty contest, but my preference is strongly for the latter.
After reviewing the code it seems that all my concerns are taken care of. It looks like it indeed iterates each individual character, not the multicharacter literals. It also looks like iterating <'hel', 'lo w', 'orld', '!'> would be the same as iterating 'hell','o wo','rld!'>. So pretty damn cool and some interesting techniques. That said, I would still contemplate pulling the c_str out of the string container proper. I would say that the mpl::string is not similar to the std::string in that it actually has to be transformed (requiring complete reconstruction) into a c_str; there's nothing about the mpl::string that renders c_str easier or particular to this container besides our prebias that it should be. That alone would indicate separation to me but additionally if the c_str was a metafunction separate from the string container, it could be used on any ForwardSequence. Something to consider anyway. Thanks for adding this.

On Wed, Apr 8, 2009 at 6:09 PM, Noah Roberts <roberts.noah@gmail.com> wrote:
After reviewing the code it seems that all my concerns are taken care of. It looks like it indeed iterates each individual character, not the multicharacter literals. It also looks like iterating <'hel', 'lo w', 'orld', '!'> would be the same as iterating 'hell','o wo','rld!'>. So pretty damn cool and some interesting techniques.
I agree with Noah. One more question, can you point to the compiler docs which you used as reference? I am just interested to read this it for my own. Many thanks, Ovanes

Ovanes Markarian wrote:
Noah Roberts wrote:
After reviewing the code it seems that all my concerns are taken care of. It looks like it indeed iterates each individual character, not the multicharacter literals. It also looks like iterating <'hel', 'lo w', 'orld', '!'> would be the same as iterating 'hell','o wo','rld!'>.
That's correct.
So pretty damn cool and some interesting techniques.
I agree with Noah.
Thanks.
One more question, can you point to the compiler docs which you used as reference? I am just interested to read this it for my own.
You mean, how did I discover the nature of the implementation-defined behavior for each compiler? It wasn't by reading any docs. I just played around with various compilers until I found what worked. I found some compiler bugs in the process, too. See: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?Feedba... -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Wed, Apr 8, 2009 at 6:57 PM, Eric Niebler <eric@boostpro.com> wrote:
You mean, how did I discover the nature of the implementation-defined behavior for each compiler? It wasn't by reading any docs. I just played around with various compilers until I found what worked. I found some compiler bugs in the process, too. See:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?Feedba...
Interesting. Ok, but if a string maps to an integer it means that I can only pass 4 characters at once on a 32bit platform??? I just looked over your tests and did not get immediately that these all use char test sequences. I used a slightly different approach in my previous use case. template<char const* Str> string {...}; extern const char some_string[] ={"abcd efg..."}; typedef string<some_string> my_string_type; Would be cool to find a solution of really passing strings like: typedef string<"abcd efg.."> some_other_type; Regards, Ovanes

Ovanes Markarian wrote:
Eric Niebler wrote:
You mean, how did I discover the nature of the implementation-defined behavior for each compiler? It wasn't by reading any docs. I just played around with various compilers until I found what worked. I found some compiler bugs in the process, too. See:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?Feedba...
Interesting. Ok, but if a string maps to an integer it means that I can only pass 4 characters at once on a 32bit platform???
Strings don't map to integers. Multicharacter literals do. And yes, that means in general that you can only reliably count on being able to encode a 4 char sequence in a multicharacter literal.
I just looked over your tests and did not get immediately that these all use char test sequences.
I don't follow you.
I used a slightly different approach in my previous use case.
template<char const* Str> string {...};
extern const char some_string[] ={"abcd efg..."};
typedef string<some_string> my_string_type;
Sure, but that gets hard to use, and you can't use this to compute new strings at compile time.
Would be cool to find a solution of really passing strings like:
typedef string<"abcd efg.."> some_other_type;
And if wishes were fishes we'd all cast nets. ;-) -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Wed, Apr 8, 2009 at 7:51 PM, Eric Niebler <eric@boost-consulting.com>wrote:
Ovanes Markarian wrote:
Eric Niebler wrote:
You mean, how did I discover the nature of the implementation-defined behavior for each compiler? It wasn't by reading any docs. I just played around with various compilers until I found what worked. I found some compiler bugs in the process, too. See:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?Feedba...
Interesting. Ok, but if a string maps to an integer it means that I can only pass 4 characters at once on a 32bit platform???
Strings don't map to integers. Multicharacter literals do. And yes, that means in general that you can only reliably count on being able to encode a 4 char sequence in a multicharacter literal.
Yes, sure. It is already late in Munich and I have headache. I meant exactly that.
I just looked over your tests and did not get immediately that these
all use char test sequences.
I don't follow you.
Sorry again. I mean that your tests are based on 4-char literals, which I did not pay attention.
I used a slightly different approach in my previous use case.
template<char const* Str> string {...};
extern const char some_string[] ={"abcd efg..."};
typedef string<some_string> my_string_type;
Sure, but that gets hard to use, and you can't use this to compute new strings at compile time.
:) But for my special use case that was enough. I defenitely share your opinion, that a library implementation should be more flexible, than my special use case impl was. On the other hand I too oft see programmers which are ignorant and even don't give a chance to a great approach. I can imagine their reaction when seeing: typdef mpl::string<'some', 'cool', 'type'> compile_time_string;
Would be cool to find a solution of really passing strings like:
typedef string<"abcd efg.."> some_other_type;
And if wishes were fishes we'd all cast nets. ;-)
Would be nice to get there ;) Cheers, Ovanes

Noah Roberts wrote:
After reviewing the code it seems that all my concerns are taken care of. It looks like it indeed iterates each individual character, not the multicharacter literals. It also looks like iterating <'hel', 'lo w', 'orld', '!'> would be the same as iterating 'hell','o wo','rld!'>. So pretty damn cool and some interesting techniques.
That said, I would still contemplate pulling the c_str out of the string container proper. I would say that the mpl::string is not similar to the std::string in that it actually has to be transformed (requiring complete reconstruction) into a c_str; there's nothing about the mpl::string that renders c_str easier or particular to this container besides our prebias that it should be. That alone would indicate separation to me but additionally if the c_str was a metafunction separate from the string container, it could be used on any ForwardSequence.
Something to consider anyway. Thanks for adding this.
That's not a bad suggestions, and I was on the fence myself about making c_str a class static of mpl::string. My reason for doing so was that getting a C-style string at compile time is really the only reason to use mpl::string, and so accessing it shouldn't incur an extra template instantiation. A separate c_str metafunction might be useful, but to be a proper metafunction, it would need to return a type, not a character array. But as with Integral Constants, we could make: mpl::c_str<FwdSeq>::type::value synonymous with: mpl::c_str<FwdSeq>::value And mpl::c_str<FwdSeq>::type is probably just a typedef for mpl::c_str<FwdSeq>. Anyway, I've invested enough time in this already and am happy with the result. If you'd like to see mpl::c_str<>, would you care to submit a patch? Or at least open a feature-request Trac ticket? -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Noah Roberts wrote:
After reviewing the code it seems that all my concerns are taken care of. It looks like it indeed iterates each individual character, not the multicharacter literals. It also looks like iterating <'hel', 'lo w', 'orld', '!'> would be the same as iterating 'hell','o wo','rld!'>. So pretty damn cool and some interesting techniques.
That said, I would still contemplate pulling the c_str out of the string container proper. I would say that the mpl::string is not similar to the std::string in that it actually has to be transformed (requiring complete reconstruction) into a c_str; there's nothing about the mpl::string that renders c_str easier or particular to this container besides our prebias that it should be. That alone would indicate separation to me but additionally if the c_str was a metafunction separate from the string container, it could be used on any ForwardSequence.
Something to consider anyway. Thanks for adding this.
That's not a bad suggestions, and I was on the fence myself about making c_str a class static of mpl::string. My reason for doing so was that getting a C-style string at compile time is really the only reason to use mpl::string, and so accessing it shouldn't incur an extra template instantiation.
Well it wouldn't exactly be 'extra' would it? The mpl::string itself would then never be instantiated since it contains nothing but typedefs and such. You might need to make "size" an enum value...but it should be at least possible to make string uninstantiated.
A separate c_str metafunction might be useful, but to be a proper metafunction, it would need to return a type, not a character array. But as with Integral Constants, we could make:
mpl::c_str<FwdSeq>::type::value
synonymous with:
mpl::c_str<FwdSeq>::value
And mpl::c_str<FwdSeq>::type is probably just a typedef for mpl::c_str<FwdSeq>.
Right, it would be a value metafunction.
Anyway, I've invested enough time in this already and am happy with the result. If you'd like to see mpl::c_str<>, would you care to submit a patch? Or at least open a feature-request Trac ticket?
I could see about doing it at home but I'm notorious for not doing so. Interesting problem though, I might get to it.

Noah Roberts wrote:
Eric Niebler wrote:
I was on the fence myself about making c_str a class static of mpl::string. My reason for doing so was that getting a C-style string at compile time is really the only reason to use mpl::string, and so accessing it shouldn't incur an extra template instantiation.
Well it wouldn't exactly be 'extra' would it? The mpl::string itself would then never be instantiated since it contains nothing but typedefs and such. You might need to make "size" an enum value...but it should be at least possible to make string uninstantiated.
I doubt any interesting metaprogram that uses mpl::string could avoid instantiating mpl::string. What I don't know is whether the templates needed to initialize mpl::string::c_str[] are instantiated even if c_str[] is never referenced. If so, those instantiations are wasted. That would be an argument in favor of moving c_str outside mpl::string. 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). It'd also be nice to be able to initialize the c_str[] array without instantiating a pile of templates.
Anyway, I've invested enough time in this already and am happy with the result. If you'd like to see mpl::c_str<>, would you care to submit a patch? Or at least open a feature-request Trac ticket?
I could see about doing it at home but I'm notorious for not doing so. Interesting problem though, I might get to it.
Yep, interesting. There are no small projects, it seems. <sigh> -- Eric Niebler BoostPro Computing http://www.boostpro.com

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. :-( -- Eric Niebler BoostPro Computing http://www.boostpro.com

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. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Sat, 11 Apr 2009 01:36:11 -0500, Eric Niebler <eric@boostpro.com> wrote:
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.
Nice work, guys! -- Aleksey Gurtovoy MetaCommunications Engineering

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

On Mon, Apr 13, 2009 at 5:45 PM, Noah Roberts <roberts.noah@gmail.com> 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

Tor Brede Vekterli wrote:
Noah Roberts wrote:
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 ;)
<snip>
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? :)
Whoa. Sick and twisted, but cool. I'm not sure what it's good for, though. After all, this: mpl::c_str<itoa_ct::apply<0xffffffff, 16>::type>::value is just an obfuscation of: "ffffffff" But it sure is fun. :-) -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Andy Stevenson wrote:
I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
It has been added to trunk as of revision 52208:
https://svn.boost.org/trac/boost/changeset/52208
No doubt the regression tests will reveal portability problems. Once they have been worked out, we can move this to release.
Visual Studio 2005 hates it. Perhaps I'm not going about it the right way? I simply downloaded string.hpp, char.hpp, and char_fwd.hpp and altered the include paths so that they'd work in an individual project. Then I wrote the following test code: #include <iostream> #include "string.hpp" template < char const* str > struct test { static void print() { std::cout << str << std::endl; } }; int main() { typedef boost::mpl::string<'hell', 'o wo', 'rld!'> str; std::cout << str::template at<0>::value << std::endl; std::cin.get(); } 1>e:\dev_workspace\experimental\scratch\scratch\main.cpp(15) : error C2976: 'boost::mpl::string<C0,C1,C2>::at' : too few template arguments 1> with 1> [ 1> C0=1751477356, 1> C1=1864398703, 1> C2=1919706145 1> ] This of course causes problems in c_str. This code fails for the same reason: #include <iostream> #include <boost/type_traits.hpp> template < typename T > struct test_inner { template < typename X, bool B = boost::is_same<T,X>::value > struct inner { static bool const value = B; }; }; int main() { std::cout << test_inner<int>::template inner<int>::value << std::endl; std::cin.get(); } So, looks like VS can't handle default template arguments in these inner templates. I changed the implementation of at<>: template < typename String, long Pos, bool B = (Pos < BOOST_MPL_MULTICHAR_LENGTH(String::front_)) > struct string_at : boost::mpl::char_<BOOST_MPL_MULTICHAR_AT(String::front_,Pos)> { }; template < typename String, long Pos > struct string_at<String, Pos, false> : string_at< typename String::rest_, Pos - BOOST_MPL_MULTICHAR_LENGTH(String::front_)> { }; template<> struct at_impl<string_tag> { template<typename Sequence, typename N> struct apply : string_at<Sequence, N::value> {}; }; And implemented c_str[] in terms of string_at<>: template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, unsigned int C)> char const string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>::c_str[] = { #define M0(z, n, data) string_at<string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS,C)>, n>::value BOOST_PP_ENUM(BOOST_MPL_STRING_MAX_LENGTH, M0, ~) #undef M0 , '\0' // to ensure the string is null-terminated }; This code compiles with changes in VS 2005: #include <iostream> #include <boost/mpl/at.hpp> #include <boost/mpl/int.hpp> #include "string.hpp" int main() { typedef boost::mpl::string<'hell', 'o wo', 'rld!'> str; std::cout << boost::mpl::at<str, boost::mpl::int_<0> >::value << std::endl; std::cout << str::c_str << std::endl; std::cin.get(); }

Noah Roberts wrote:
Eric Niebler wrote:
Andy Stevenson wrote:
I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
It has been added to trunk as of revision 52208:
https://svn.boost.org/trac/boost/changeset/52208
No doubt the regression tests will reveal portability problems. Once they have been worked out, we can move this to release.
Visual Studio 2005 hates it.
<snip> Is that msvc-7.1? If so, I have already fixed the problem in changeset 52241. You can see that the string tests are passing for msvc-7.1, -8.0 and -9.0 by looking at the regression results. Thanks, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Noah Roberts wrote:
Eric Niebler wrote:
Andy Stevenson wrote: > > I recall some discussion of there being an mpl::string > template..... Can't see it in the mpl library. Is it elsewhere?
It has been added to trunk as of revision 52208:
https://svn.boost.org/trac/boost/changeset/52208
No doubt the regression tests will reveal portability problems. Once they have been worked out, we can move this to release.
Visual Studio 2005 hates it.
<snip>
Is that msvc-7.1? If so, I have already fixed the problem in changeset 52241. You can see that the string tests are passing for msvc-7.1, -8.0 and -9.0 by looking at the regression results.
No, it's msvc-8.0 Regression results aside, this doesn't compile: #include <iostream> #include <boost/mpl/at.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/string.hpp> int main() { typedef boost::mpl::string<'hell', 'o wo', 'rld!'> str; std::cout << boost::mpl::at<str, boost::mpl::int_<0> >::value << std::endl; std::cout << str::c_str << std::endl; std::cin.get(); } Again, I simply copied char.hpp, char_fwd.hpp, and string.hpp into boost 1.37 It could be that it's because I'm not grabbing the entire boost tree from svn but since I can replicate the problem with a basic program that's using the same techniques you are, I really doubt that. Looking deeper, you need to change: #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) to: #if BOOST_WORKAROUND(BOOST_MSVC, <= 1400) Alternatively, you could just keep telling me it's working and I'll go away. I'm not loaded with a lot of spare time either.

Noah Roberts wrote:
Looking deeper, you need to change:
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310) to: #if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
Alternatively, you could just keep telling me it's working and I'll go away. I'm not loaded with a lot of spare time either.
Totally my bad. You're right. Looks like we don't have testers for msvc-8.0, and I overlooked that. It should be fixed now. Thanks for the report, and my apologies. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Thanks Eric.... would be a useful addition to mpl I think at some point. Great for DSLs which is how I intend to use it. Andy On 30 Mar 2009, at 04:58, Eric Niebler wrote:
Andy Stevenson wrote:
Hi, I recall some discussion of there being an mpl::string template..... Can't see it in the mpl library. Is it elsewhere?
I wrote one once and intended to write docs and tests and integrate it into MPL but never got around to it. You can find it here:
http://archives.free.net.ph/message/20080324.060757.9880ea2b.el.html
-- Eric Niebler BoostPro Computing http://www.boostpro.com
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (9)
-
Aleksey Gurtovoy
-
Andy Stevenson
-
Dominique Devienne
-
Eric Niebler
-
Eric Niebler
-
Jesse Perla
-
Noah Roberts
-
Ovanes Markarian
-
Tor Brede Vekterli