[proto] problem with templated recursive transform
Hi,
I have gotten my hands pretty dirty with my array expression DSEL, and
hove gotten surprisingly far (surprisingly considering the amounts of
black template magic involved :) ).
Now I am stuck with a templated recursive transform, that I cant seem to
get right. Here is a stripped down version:
template
{}; so what does work is when I have the first case (i.e. the expression is just an indexed array terminal), but the second case, where it recurses breaks on instantiation. I have tried all the tricks from the proto docs, i.e. adding a dummy callable template parameter, specializing boost::proto:::is_callable, and wrapping the recursion in proto::call, always the same long error. It also works when ExpressionIteratorBuilder is not a template, though that would not make it very useful. Any ideas? Otherwise I am beginning to love proto, and am looking forward to c++0x when the error messages might become readable through concepts :). Best Daniel -- --- Daniel Oberhoff Fraunhofer FIT Schloss Birlinghoven 53754 Sankt Augustin, Germany Tel.: +49-(0)-2241-14-3486 Fax.:+49 (0) 2241/14-2080
Daniel Oberhoff wrote:
Hi,
I have gotten my hands pretty dirty with my array expression DSEL, and hove gotten surprisingly far (surprisingly considering the amounts of black template magic involved :) ).
Now I am stuck with a templated recursive transform, that I cant seem to get right.
<snip>
It also works when ExpressionIteratorBuilder is not a template, though that would not make it very useful.
Any ideas?
Could you pls. send either a complete example that I could compile here, or at least the error message? I'd prefer a complete example.
Otherwise I am beginning to love proto, and am looking forward to c++0x when the error messages might become readable through concepts :).
Whether and how to conceptify Proto is an open question. So I'm sorry to say that it's not at all certain that C++0x will bring better error messages for Proto. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Hi,
On 2009-02-05 16:47:15 +0100, Eric Niebler
Daniel Oberhoff wrote:
Hi,
I have gotten my hands pretty dirty with my array expression DSEL, and hove gotten surprisingly far (surprisingly considering the amounts of black template magic involved :) ).
Now I am stuck with a templated recursive transform, that I cant seem to get right.
<snip>
It also works when ExpressionIteratorBuilder is not a template, though that would not make it very useful.
Any ideas?
Could you pls. send either a complete example that I could compile here, or at least the error message? I'd prefer a complete example.
Sorry, I had hoped there was something obviously broken. Like templating a transform based on proto::or_/proto::when. I placed a zip-file here with the files here: http://danieloberhoff.de/files/for_eric There are four headers and a test-suite, based on cppunit. The expression that breaks is on line 59. Makefile is also there. If that is too messy for you I can try to trim it down to just this problem. The class that breaks is at the end of CPUDataNDExpressionIterators.hpp.
Otherwise I am beginning to love proto, and am looking forward to c++0x when the error messages might become readable through concepts :).
Whether and how to conceptify Proto is an open question. So I'm sorry to say that it's not at all certain that C++0x will bring better error messages for Proto.
I was actually fearing that. But in this case: wouldn't it somehow be possible to state "your type is not callable" or something like that? Best Daniel
Daniel Oberhoff wrote:
I placed a zip-file here with the files here:
http://danieloberhoff.de/files/for_eric
There are four headers and a test-suite, based on cppunit. The expression that breaks is on line 59. Makefile is also there. If that is too messy for you I can try to trim it down to just this problem. The class that breaks is at the end of CPUDataNDExpressionIterators.hpp.
Please try to reduce the problem as much as you can, and also keep in mind that I don't have cppunit.
Whether and how to conceptify Proto is an open question. So I'm sorry to say that it's not at all certain that C++0x will bring better error messages for Proto.
I was actually fearing that. But in this case: wouldn't it somehow be possible to state
"your type is not callable"
or something like that?
Possibly. I haven't looked into it. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Daniel Oberhoff wrote:
Sorry, I had hoped there was something obviously broken. Like templating a transform based on proto::or_/proto::when. I placed a zip-file here with the files here:
http://danieloberhoff.de/files/for_eric
There are four headers and a test-suite, based on cppunit. The expression that breaks is on line 59. Makefile is also there. If that is too messy for you I can try to trim it down to just this problem. The class that breaks is at the end of CPUDataNDExpressionIterators.hpp.
I removed the dependency on cppunit (not hard), adding a missing #include <vector>, removed spurious semicolons after BOOST_PROTO_EXTENDS() and BOOST_PROTO_BASIC_EXTENDS(), and after that, the only problem I saw was this on line 62 of CPUDataNDExpressions.hpp: proto::function< proto::terminal< CPUDataND_< T > >, index_grammar, index_grammar, index_grammar, index_grammar, index_grammar > This requires BOOST_PROTO_MAX_ARITY to be set to 6, whereas by default it is set to 5. After deleting this line, everything compiles and runs just fine for me. I'm using gcc-4.3. Much work would be necessary to make this work with msvc, which has a much harder time with the nested function types used in callable and object transforms. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com
On 2009-02-07 00:18:05 +0100, Eric Niebler
Daniel Oberhoff wrote:
Sorry, I had hoped there was something obviously broken. Like templating a transform based on proto::or_/proto::when. I placed a zip-file here with the files here:
http://danieloberhoff.de/files/for_eric
There are four headers and a test-suite, based on cppunit. The expression that breaks is on line 59. Makefile is also there. If that is too messy for you I can try to trim it down to just this problem. The class that breaks is at the end of CPUDataNDExpressionIterators.hpp.
I removed the dependency on cppunit (not hard), adding a missing #include <vector>, removed spurious semicolons after BOOST_PROTO_EXTENDS() and BOOST_PROTO_BASIC_EXTENDS(), and after that, the only problem I saw was this on line 62 of CPUDataNDExpressions.hpp:
wow, thanks for taking the time. I didnt even see those errors. maybe I should have enabled more warnings?
proto::function< proto::terminal< CPUDataND_< T > >, index_grammar, index_grammar, index_grammar, index_grammar, index_grammar >
This requires BOOST_PROTO_MAX_ARITY to be set to 6, whereas by default it is set to 5. After deleting this line, everything compiles and runs just fine for me.
ok. will c++0x variadic templates help here?
I'm using gcc-4.3. Much work would be necessary to make this work with msvc, which has a much harder time with the nested function types used in callable and object transforms.
Is there any other way of doing this like this? I really like callable transforms, because they at once can synthesize types and perform semantic actions at run-time. It really helped constructing the expression iterators. It felt like using eval contexts would impose much more runtime overhead and complicated type construction.
Daniel Oberhoff wrote:
On 2009-02-07 00:18:05 +0100, Eric Niebler
said: I removed the dependency on cppunit (not hard), adding a missing #include <vector>, removed spurious semicolons after BOOST_PROTO_EXTENDS() and BOOST_PROTO_BASIC_EXTENDS(), and after that, the only problem I saw was this on line 62 of CPUDataNDExpressions.hpp:
wow, thanks for taking the time. I didnt even see those errors. maybe I should have enabled more warnings?
Probably. :-)
proto::function< proto::terminal< CPUDataND_< T > >, index_grammar, index_grammar, index_grammar, index_grammar, index_grammar >
This requires BOOST_PROTO_MAX_ARITY to be set to 6, whereas by default it is set to 5. After deleting this line, everything compiles and runs just fine for me.
ok. will c++0x variadic templates help here?
I've experimented with a variadic Proto. It's not without its problems.
Consuming variadic parameter packs requires recursive templates, so a
completely variadic Proto actually compiles *much* slower. A good way to
see this is to recognize that there is no way using variadic class
templates for this:
template
I'm using gcc-4.3. Much work would be necessary to make this work with msvc, which has a much harder time with the nested function types used in callable and object transforms.
Is there any other way of doing this like this? I really like callable transforms, because they at once can synthesize types and perform semantic actions at run-time. It really helped constructing the expression iterators. It felt like using eval contexts would impose much more runtime overhead and complicated type construction.
I've filed bugs against msvc for its mishandling of nested function types. In the mean time, please continue using callable transforms if you like them. You can always wrap them in proto::call<> (or, for object transforms, proto::make<>) to keep msvc happy, if that's a compiler you care about. -- Eric Niebler BoostPro Computing http://www.boostpro.com
On 2009-02-07 01:06:16 +0100, Eric Niebler
proto::function< proto::terminal< CPUDataND_< T > >, index_grammar, index_grammar, index_grammar, index_grammar, index_grammar >
This requires BOOST_PROTO_MAX_ARITY to be set to 6, whereas by default it is set to 5. After deleting this line, everything compiles and runs just fine for me.
ok. will c++0x variadic templates help here?
I've experimented with a variadic Proto. It's not without its problems. Consuming variadic parameter packs requires recursive templates, so a completely variadic Proto actually compiles *much* slower. A good way to see this is to recognize that there is no way using variadic class templates for this:
template
struct vector { /*what goes here???*/ }; to generate a class like this:
template
struct vector { A0 a0; ... An an; }; That is, you can't generate a flat struct from a variadic class template. With a variadic class template, you need to play games with inheritance or head and tail data members, which causes this to instantiate O(N) templates. So chances are, Proto will always have a hard-coded upper limit on the number of child nodes.
ah, ok, bummer. A friend of mine recently mused if it wasn't time for a new language. not like python, more like D. Not that I particularly like D (well, I don't really know it either), just that it seems people have taken c++ to it's limits, and c++0x can't really help totally, because it is an incremental change (even though auto will be great I think, as will variadic function templates and move semantics). I opposed him at the time, but seeing how much black magic goes into ETs (or DSELs in general), he might be right after all.
I've filed bugs against msvc for its mishandling of nested function types. In the mean time, please continue using callable transforms if you like them. You can always wrap them in proto::call<> (or, for object transforms, proto::make<>) to keep msvc happy, if that's a compiler you care about.
Ok, that isn't the worst of solutions, if I end up needing msvc (which may actually be the case soon, as we may be required to write plugins for windows programs with this stuff...). Thanks again for taking the time and giving something like proto to the community. Daniel
Daniel Oberhoff wrote:
I've experimented with a variadic Proto. It's not without its problems. <snip> ah, ok, bummer. A friend of mine recently mused if it wasn't time for a new language. not like python, more like D. Not that I particularly like D (well, I don't really know it either), just that it seems people have taken c++ to it's limits, and c++0x can't really help totally, because it is an incremental change (even though auto will be great I think, as will variadic function templates and move semantics). I opposed him at
Eric Niebler wrote: the time, but seeing how much black magic goes into ETs (or DSELs in general), he might be right after all.
If programming language evolution stopped at C++, I would be shocked and disappointed. That said, I don't think C++ has been taken to its limits. I'm curious to see what the next generation of C++ programmers will do with new features like concepts, variadics and rvalue references. If you're sweating the black magic that goes into building a DSELs, then I suggest you don't think so hard about how the sausage is made. ;-)
I've filed bugs against msvc for its mishandling of nested function types. In the mean time, please continue using callable transforms if you like them. You can always wrap them in proto::call<> (or, for object transforms, proto::make<>) to keep msvc happy, if that's a compiler you care about.
Ok, that isn't the worst of solutions, if I end up needing msvc (which may actually be the case soon, as we may be required to write plugins for windows programs with this stuff...).
You can get pretty far with preprocessor hacks to hide the msvc workarounds. Here's something to get your gears turning: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) #define _value(x) callproto::_value(x) #endif Now, if proto::_value(proto::_left) shows up in your grammar, it gets turned into proto::callproto::_value(proto::_left). I use this trick a lot.
Thanks again for taking the time and giving something like proto to the community.
My pleasure. I'm glad to see folks starting to use it. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler
You can get pretty far with preprocessor hacks to hide the msvc workarounds. Here's something to get your gears turning:
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) #define _value(x) callproto::_value(x) #endif
Now, if proto::_value(proto::_left) shows up in your grammar, it gets turned into proto::callproto::_value(proto::_left). I use this trick a lot.
Cool stuff, Eric, but I nearly missed that one. Could you copy'n'paste this to the "Unsorted tips and tricks" section of the proto docs? Markus (Who is forced to program in C#/CLI for a while instead of working with proto :-( )
participants (4)
-
Daniel Oberhoff
-
Daniel Oberhoff
-
Eric Niebler
-
Markus Werle