
Hello Fellow Boosters, I have just completed implementing support for "Variadic Templates" in GCC. Variadic templates are C++ templates that can accept any number of "extra" template arguments, just like a function that uses C-style varargs (with "...") can accept any number of extra arguments. Unlike C varags, however, variadic templates work both for class templates and function templates, and are completely type-safe. Why do variadic templates matter for Boost? For one thing, they will allow us to eliminate the use of preprocessor metaprogramming in many, many places throughout the library. This can simplify our library implementations drastically, and eliminate those annoying "caps" on the number of arguments one can use (ever tried to use bind () with 11 arguments?). Beyond that, variadic templates are just plain fun, and there are undoubtedly a great number of metaprogramming applications. Here are a few teasers to illustrate what variadic templates can do: We can implement an MPL-like type vector with one line of code: template<typename... Types> struct vector { }; The "ellipsis" means that we can pack any number of arguments into the "template parameter pack" called Types. Of course, we can do the same for MPL's vector_c: template<typename T, T... Values> struct vector_c { }; Unimpressed? Here's an implementation of tuple that accepts any number of element types: template<typename... Values> class tuple; template<> class tuple<> { }; template<typename Head, typename... Tail> class tuple<Head, Tail...> : private tuple<Tail...> { protected: Head m_head; }; We're using recursion to build up the tuple. The ellipsis operator works with partial specializations, too, packing together "extra" arguments at the end. Of course, all of this would be useless if we couldn't write some of the other tuple operations, like operator==: inline bool operator==(const tuple<>&, const tuple<>&) { return true; } template<typename T, typename... TTail, typename U, typename... UTail> bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { return t.head() == u.head() && t.tail() == u.tail(); } Variadic function templates can accept any number of function arguments, so we can now (finally!) implement a type-safe printf() without mangling the tried-and-true printf() syntax or restricting ourselves to POD types: void printf(const char* s) { while (*s) { if (*s == '%' && *++s != '%') throw std::runtime_error("invalid format string: missing arguments"); std::cout << *s++; } } template<typename T, typename... Args> void printf(const char* s, const T& value, const Args&... args) { while (*s) { if (*s == '%' && *++s != '%') { std::cout << value; return printf(++s, args...); } std::cout << *s++; throw std::runtime_error("extra arguments provided to printf"); } I've also built prototypes of of Function and Bind, among other things. The Bind example is especially interesting, and worth a read (see below) Interested? There is more information and a complete implementation in GCC available at: http://www.generic-programming.org/~dgregor/cpp/variadic- templates.html I've written two documents describing variadic templates in more detail: http://www.generic-programming.org/~dgregor/cpp/brief-intro.pdf : A brief introduction to variadic templates, that walks through the printf() implementation. http://www.generic-programming.org/~dgregor/cpp/variadic- templates.pdf : A complete proposal to introduce variadic templates into C++0x. This contains annotated versions of the tuple, function, and bind prototypes along with a detailed description of the capabilities of variadic templates. The GCC implementation is complete, supporting all of the features described in the proposal. I've used it for proof-of-concept implementations of several libraries. In the (near) future, I hope to introduce variadic templates support into the "official" GCC, but I need your help! Are variadic templates worthwhile? Will they help us build better, cleaner Boost libraries in the future? Should we bring variadic templates to the C++ committee, to enable better implementations of TR1 components and eliminate the need for much of the preprocessor metaprogramming we do today? Feedback is greatly appreciated. Cheers Doug Gregor Open Systems Lab @ Indiana University

Funky idea! Can't get to the PDFs, though. Cromwell D. Enage __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

Damn! Funky, and Cool too. Likewise however, I can't get to the PDFs. I am drooling at the chance of playing with this. It may be presumptuous of me (not seeing the PDFs), but I am willing to give my vote to this. -- Manfred Doudar - Research Engineer National ICT Australia - Canberra Research Lab | www.nicta.com.au Research School of Information Sciences and Engineering (RSISE) The Australian National University - Canberra, ACT 0200 AUSTRALIA Cromwell Enage wrote:
Funky idea! Can't get to the PDFs, though.
Cromwell D. Enage
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 8/4/06, Cromwell Enage <sponage@yahoo.com> wrote:
Funky idea! Can't get to the PDFs, though.
I couldn't reach them either through the links in the posting, but was able to download them via the links on the web page. But both failed to open, with a message from Adobe Reader 7.0.8 (Windows) that the files were corrupted:-( --Beman

Funky idea! Can't get to the PDFs, though.
Oops, my mistake. The PDFs should now be accessible. FWIW, there's a minor bug in my GCC patch that causes problems with out-of-line member function definitions for classes. Put your member function deifnitions in-line for now, and I'll have a fix "shortly." Doug

Doug Gregor wrote:
I have just completed implementing support for "Variadic Templates" in GCC. Variadic templates are C++ templates that can accept any number of "extra" template arguments, just like a function that uses C-style varargs (with "...") can accept any number of extra arguments. Unlike C varags, however, variadic templates work both for class templates and function templates, and are completely type-safe.
A dream come true ... http://groups.google.com/group/comp.std.c++/browse_frm/thread/9432727bc5e67d48/947b100b5ee21f6e?lnk=st&q=&rnum=9&hl=it#947b100b5ee21f6e ... now I'm going to dig up what my need actually was at the time.
Unimpressed? Here's an implementation of tuple that accepts any number of element types:
template<typename... Values> class tuple;
template<> class tuple<> { };
template<typename Head, typename... Tail> class tuple<Head, Tail...> : private tuple<Tail...> {
protected: Head m_head; };
The fact that head() and tail() are not declareda bove is just an omission, is it ?
Are variadic templates worthwhile? Will they help us build better, cleaner Boost libraries in the future? Should we bring variadic templates to the C++ committee, to enable better implementations of TR1 components and eliminate the need for much of the preprocessor metaprogramming we do today? Feedback is greatly appreciated.
Davide Bolcioni -- There is no place like /home.

On Aug 5, 2006, at 4:40 AM, Davide Bolcioni wrote:
Unimpressed? Here's an implementation of tuple that accepts any number of element types:
template<typename... Values> class tuple;
template<> class tuple<> { };
template<typename Head, typename... Tail> class tuple<Head, Tail...> : private tuple<Tail...> {
protected: Head m_head; };
The fact that head() and tail() are not declareda bove is just an omission, is it ?
Yes, the (now accessible) PDFs have the complete code. Doug

Doug Gregor wrote:
Hello Fellow Boosters,
I have just completed implementing support for "Variadic Templates" in GCC. Variadic templates are C++ templates that can accept any number of "extra" template arguments, just like a function that uses C-style varargs (with "...") can accept any number of extra arguments. Unlike C varags, however, variadic templates work both for class templates and function templates, and are completely type-safe.
Wow, very cool idea, but the pdf's aren't on the web site it seems. John.

Doug Gregor wrote:
Hello Fellow Boosters,
I have just completed implementing support for "Variadic Templates" in GCC. Variadic templates are C++ templates that can accept any number of "extra" template arguments, just like a function that uses C-style varargs (with "...") can accept any number of extra arguments. Unlike C varags, however, variadic templates work both for class templates and function templates, and are completely type-safe.
Doug, as always, you rock! Cheers! -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

On Aug 4, 2006, at 5:54 PM, Doug Gregor wrote:
I've written two documents describing variadic templates in more detail:
http://www.generic-programming.org/~dgregor/cpp/brief-intro.pdf : A brief introduction to variadic templates, that walks through the printf() implementation.
http://www.generic-programming.org/~dgregor/cpp/variadic- templates.pdf : A complete proposal to introduce variadic templates into C++0x. This contains annotated versions of the tuple, function, and bind prototypes along with a detailed description of the capabilities of variadic templates.
These documents are now accessible. My apologies.
The GCC implementation is complete, supporting all of the features described in the proposal. I've used it for proof-of-concept implementations of several libraries. In the (near) future, I hope to introduce variadic templates support into the "official" GCC, but I need your help!
The web page now contains an updated GCC implementation that fixes problems with out-of-line template definitions for variadic templates.
http://www.generic-programming.org/~dgregor/cpp/variadic- templates.html
Cheers, Doug

http://www.generic-programming.org/~dgregor/cpp/variadic- templates.pdf : A complete proposal to introduce variadic templates into C++0x. This contains annotated versions of the tuple, function, and bind prototypes along with a detailed description of the capabilities of variadic templates.
Very nice work. Definitely variadic templates are very interesting. I see that you have chosen the "core" set of the previous paper menu. You have discarded other more advanced features like "pairwise expansion"? This feature was _very_ interesting to implement perfect forwarding and in-place constructors. First-class parameter packs were also a huge compile-time improvement, because recursiveness approach is quite inefficient comparing it to macro/first class approach. So the question is, are "advanced" features discarded for C++0x or you are just preparing them for a future paper? Regards, Ion

I see that you have chosen the "core" set of the previous paper menu. You have discarded other more advanced features like "pairwise expansion"? This feature was _very_ interesting to implement perfect forwarding and in-place constructors.
Oooops! I see in the paper that perfect forwarding is present along with other features but are not explicitly listed. I thought that "core" features was N1704's "Common cases" prepackaged features option. Could you say which features of the N1704's list have you implement or plan to implement? The full list was: -> Basic variadic templates -> First-class parameter packs -> Initializer lists are parameter packs -> Ellipsis operator for classes -> Length of parameter packs -> Get Nth element for parameter pack -> Arbitrary expansion -> Nested expansion -> Pairwise expansion -> Folding expansion -> Arbitrary matching patterns -> Pairwise matching patterns Sorry for the previous erroneous mail. Regards, Ion

On Aug 5, 2006, at 3:04 PM, Ion Gaztañaga wrote:
I see that you have chosen the "core" set of the previous paper menu. You have discarded other more advanced features like "pairwise expansion"? This feature was _very_ interesting to implement perfect forwarding and in-place constructors.
Oooops! I see in the paper that perfect forwarding is present along with other features but are not explicitly listed. I thought that "core" features was N1704's "Common cases" prepackaged features option. Could you say which features of the N1704's list have you implement or plan to implement? The full list was:
-> Basic variadic templates
Implemented.
-> First-class parameter packs
Will not be implemented. There are serious technical problems with implementing first-class parameter packs that we had not foreseen. In particular, to do a decent job of making sure parameter packs are used properly when a template is defined, you need to know *exactly* which things are parameter packs and which things aren't. With first- class parameter packs, you don't always have this information because.
-> Initializer lists are parameter packs
Still thinking about this one. It looks like it might be a good idea.
-> Ellipsis operator for classes
Not implemented. I imagine there are better ways to do reflection/ introspection. I think overloading of the ellipsis operator was also part of this section. This has some of the same technical issues as first-class parameter packs. But, check out the "indexes" trick for "unpacking" the values in a tuple<> with "...".
-> Length of parameter packs
Implemented.
-> Get Nth element for parameter pack
Not implemented, but I'm seriously considering it. We'd need to introduce a new operator (".[]" has been suggested), which worries me slightly. C++ already has a lot of operators :)
-> Arbitrary expansion
Implemented.
-> Nested expansion
I haven't really tested this one much, but I believe it will work so long as the outer and inner pack/unpack expressions have disjoint parameter packs.
-> Pairwise expansion
Implemented.
-> Folding expansion
Will not be implemented. It's powerful, sure, but it's just... too... weird.
-> Arbitrary matching patterns
Implemented.
-> Pairwise matching patterns
Implemented. Cheers, Doug

[moderator: this might be a bit off-topic, sorry] Douglas Gregor wrote:
On Aug 5, 2006, at 3:04 PM, Ion Gaztañaga wrote:
-> First-class parameter packs
Will not be implemented. There are serious technical problems with implementing first-class parameter packs that we had not foreseen. In particular, to do a decent job of making sure parameter packs are used properly when a template is defined, you need to know *exactly* which things are parameter packs and which things aren't. With first- class parameter packs, you don't always have this information because.
Umm. Native tuple without needing recursive instantiation trick was a very good idea to speed up compilation. Maybe the next time!
-> Initializer lists are parameter packs
Still thinking about this one. It looks like it might be a good idea.
In your vector example, the parameter list is introduced with a recursive function: template<typename T> class vector { public: template<typename... Values> vector(const Values&... values) { reserve(sizeof(values...)); push back all(values...); } private: void push_back_all() { } template<typename... Values> void push_back_all(const T& value, const Values&... values) { push_back(value); push_back_all(values...); } }; It would nice (just an idea) to have a way to execute an expression for every parameter, just like it was a function unrolling, implemented with with macros: template<typename... Values> void push back all(const T& value, const Values&... values) { std::variadic_unroll(push_back(value)); } Just an idea for the future. I don't know if implementing this is too difficult. That would help with compilation time.
Lots of good stuff implemented
*Very* nice work. Looks impressive. Ion

On Aug 5, 2006, at 9:06 PM, Ion Gaztañaga wrote:
[moderator: this might be a bit off-topic, sorry]
Naah, don't worry about it. Boost isn't about effecting change in the language, but some changes could have enough of an impact on Boost to warrant discussion. Besides, I'm hoping that the Boost membership can come up with some good new tricks with variadic templates :)
Douglas Gregor wrote:
On Aug 5, 2006, at 3:04 PM, Ion Gaztañaga wrote:
-> First-class parameter packs
Will not be implemented. There are serious technical problems with implementing first-class parameter packs that we had not foreseen. In particular, to do a decent job of making sure parameter packs are used properly when a template is defined, you need to know *exactly* which things are parameter packs and which things aren't. With first- class parameter packs, you don't always have this information because.
Umm. Native tuple without needing recursive instantiation trick was a very good idea to speed up compilation. Maybe the next time!
Sure, but that's a much bigger change to the language, and adding a primitive tuple met some some implementor resistance. Eliminating the need for the preprocessor to generate N versions of tuple, function, bind, etc. should improve compile times quite nicely.
-> Initializer lists are parameter packs
Still thinking about this one. It looks like it might be a good idea.
In your vector example, the parameter list is introduced with a recursive function:
template<typename T> class vector { public: template<typename... Values> vector(const Values&... values) { reserve(sizeof(values...)); push back all(values...); } private: void push_back_all() { } template<typename... Values> void push_back_all(const T& value, const Values&... values) { push_back(value); push_back_all(values...); } };
It would nice (just an idea) to have a way to execute an expression for every parameter, just like it was a function unrolling, implemented with with macros:
template<typename... Values> void push back all(const T& value, const Values&... values) { std::variadic_unroll(push_back(value)); }
Just an idea for the future. I don't know if implementing this is too difficult. That would help with compilation time.
Oh, you can do that already, if you don't mind turning that push_back call into a non-void expression: template<typename... Args> void variadic_unroll(const Args&...) { } template<typename... Values> void push_back_all(const Values&... values) { variadic_unroll((push_back(values), 0)...); } Doug

It would nice (just an idea) to have a way to execute an expression for every parameter, just like it was a function unrolling, implemented with with macros:
template<typename... Values> void push back all(const T& value, const Values&... values) { std::variadic_unroll(push_back(value)); }
Just an idea for the future. I don't know if implementing this is too difficult. That would help with compilation time.
Oh, you can do that already, if you don't mind turning that push_back call into a non-void expression:
template<typename... Args> void variadic_unroll(const Args&...) { }
template<typename... Values> void push_back_all(const Values&... values) { variadic_unroll((push_back(values), 0)...); }
Good. I can set the bar higher if you want ;-). What about storing the return value in a tuple: bool test() { /**/ } template<typename... Values> void test_all(const Values&... values) { //Is this possible? //tuple<decltype(test(Values))...> ret_tuple = ... //or using "auto" auto ret_tuple = variadic_unroll(test(values)); } It would be also nice a way to define a tuple of N objects of the same type: auto tup = make_tuple_n<bool, 6>; And iterate at runtime in a tuple of N objects of the same type, to get each value (the iterator would climb in the inheritance-emulation code when incremeting it): for( bool ok : ret_tuple ) std::cout << "return value:" << ok; Keep up the good work! Ion

Ion Gaztañaga wrote:
It would be also nice a way to define a tuple of N objects of the same type: auto tup = make_tuple_n<bool, 6>;
Isn't this spelled: std::tr1::array< bool, 6 > tup; ? tr1 array should supply everything necessary to act as a homogeneous tuple, other than using the actual name 'tuple' - which I guess could show up in some template specialization cases. -- AlisdairM

AlisdairM wrote:
Ion Gaztañaga wrote:
It would be also nice a way to define a tuple of N objects of the same type: auto tup = make_tuple_n<bool, 6>;
Isn't this spelled:
std::tr1::array< bool, 6 > tup; ?
tr1 array should supply everything necessary to act as a homogeneous tuple, other than using the actual name 'tuple' - which I guess could show up in some template specialization cases.
Yes, I'm reinventing the wheel ;-). And I could surely iterate over it! The tuple approach should be maybe used when the function unrolling has a different return type: template<class T> T multiply(T t){ return T*=2; } template<typename... Values> auto multiply_and_pack(const Values&... values) -> decltype(/**/){ auto ret_tuple = variadic_unroll(multiply(values)); return ret_tuple; } And what if Values parameter pack is instantiated as a sequence of the same type? Should we make tuple<int, int> and array<int, 2> the same type? Regards, Ion

On Aug 6, 2006, at 7:10 AM, Ion Gaztañaga wrote:
And what if Values parameter pack is instantiated as a sequence of the same type? Should we make tuple<int, int> and array<int, 2> the same type?
They should be the same type, but there should be a common interface that allows one to act on both types in the same way. IIRC, array<> works with tuple_size, tuple_element, and get, so we already have that interface. Doug

Douglas Gregor wrote:
On Aug 6, 2006, at 7:10 AM, Ion Gaztañaga wrote:
And what if Values parameter pack is instantiated as a sequence of the same type? Should we make tuple<int, int> and array<int, 2> the same type?
They should be the same type, but there should be a common interface that allows one to act on both types in the same way. IIRC, array<> works with tuple_size, tuple_element, and get, so we already have that interface.
And Fusion regards boost::array as a fully conforming sequence. All the facilities (algorithms, etc.) are available for array. It is interesting to note that Dan (Marsden) did some tests and found that fusion algorithms on boost::array with vc8.0 "significantly outperforms the standard library equivalent code, presumably as it has more information available at compile time, and with inlining it effectively unrolls the entire loops". Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Douglas Gregor wrote:
On Aug 6, 2006, at 7:10 AM, Ion Gaztañaga wrote:
And what if Values parameter pack is instantiated as a sequence of the same type? Should we make tuple<int, int> and array<int, 2> the same type?
They should be the same type, but there should be a common interface that allows one to act on both types in the same way. IIRC, array<> works with tuple_size, tuple_element, and get, so we already have that interface.
Thanks for all the replies. Variadic templates look _very_ exciting. When I saw in pre-Berlin evolution state that it in thte "Not ready for C++0x, but encourage work to continue" work, I was very disappointed. But now that after Berlin the state has improved and with the prototype compiler, I hope we can get it into C++0x. Thanks, Ion

On Aug 6, 2006, at 6:13 AM, Ion Gaztañaga wrote:
Good. I can set the bar higher if you want ;-). What about storing the return value in a tuple:
bool test() { /**/ }
template<typename... Values> void test_all(const Values&... values) { //Is this possible? //tuple<decltype(test(Values))...> ret_tuple = ...
//or using "auto" auto ret_tuple = variadic_unroll(test(values)); }
No need for a "variadic_unroll"; just use make_tuple: auto ret_tuple = make_tuple(test(values)...)
It would be also nice a way to define a tuple of N objects of the same type: auto tup = make_tuple_n<bool, 6>;
I bet you can write a short metaprogram to do this using variadic templates.
And iterate at runtime in a tuple of N objects of the same type, to get each value (the iterator would climb in the inheritance-emulation code when incremeting it):
for( bool ok : ret_tuple ) std::cout << "return value:" << ok;
As Alisdair points out, we have array<>, which we can easily loop over. And, of course, that std::cout << ... bit is just an expression, so you can "unroll" the loop like this: variadic_unroll(std::cout << "return value: " << ret_tuple...); Cheers, Doug

This looks very nice. I hope the standards committee accepts it. I do have one question: is it possible to define a variadic function such that all the variadic parameters are of the same type? This would be useful, for instance, to define a max() function that can finds the max value of any number of parameters: long x1, x2, x3, x4, x5; // Some code const long &max_x = max(x1, x2, x3, x4, x5); If this is possible, would it be possible to define a variadic function without making it a template function? Joe

On Aug 5, 2006, at 8:03 PM, Joe Gottman wrote:
This looks very nice. I hope the standards committee accepts it. I do have one question: is it possible to define a variadic function such that all the variadic parameters are of the same type? This would be useful, for instance, to define a max() function that can finds the max value of any number of parameters:
long x1, x2, x3, x4, x5; // Some code const long &max_x = max(x1, x2, x3, x4, x5);
If this is possible, would it be possible to define a variadic function without making it a template function?
There's a mention of something similar in the section on interactions with initializer lists. This could be an interesting way to go. We'd have to see more examples, and look into the implementation of max() as well. Doug

Douglas Gregor wrote:
On Aug 5, 2006, at 8:03 PM, Joe Gottman wrote:
This looks very nice. I hope the standards committee accepts it. I do have one question: is it possible to define a variadic function such that all the variadic parameters are of the same type? This would be useful, for instance, to define a max() function that can finds the max value of any number of parameters:
long x1, x2, x3, x4, x5; // Some code const long &max_x = max(x1, x2, x3, x4, x5);
If this is possible, would it be possible to define a variadic function without making it a template function?
There's a mention of something similar in the section on interactions with initializer lists. This could be an interesting way to go. We'd have to see more examples, and look into the implementation of max() as well.
Mow, if we could just apply the "homogeneous" concept to the parameter pack ... -- AlisdairM

Joe Gottman wrote:
This looks very nice. I hope the standards committee accepts it. I do have one question: is it possible to define a variadic function such that all the variadic parameters are of the same type? This would be useful, for instance, to define a max() function that can finds the max value of any number of parameters:
long x1, x2, x3, x4, x5; // Some code const long &max_x = max(x1, x2, x3, x4, x5);
If this is possible, would it be possible to define a variadic function without making it a template function?
FWIW, you can do that today by providing an overload of std::mac_element: template< class Rng > range_iterator<Rng>::const_iterator max_element( const Rng& r ) { return std::max_element( boost::begin(r), boost::end(r) ); } const long& max = *max_element( boost::assign::ref_list_of(x1)(x2)(x3)(x4) ); -Thorsten

Hello, Doug Gregor wrote:
template<typename... Types> struct vector { };
This looks really nice. My understanding is that <typename... Types> would be an ordered list of types. In some cases, you might be interested in an unique set though (boost::any); is there some way to express that the list of types should be "normalized" in some way, or is that an entirely different beast? Simon

On Aug 7, 2006, at 4:39 AM, Simon Richter wrote:
Hello,
Doug Gregor wrote:
template<typename... Types> struct vector { };
This looks really nice.
My understanding is that <typename... Types> would be an ordered list of types.
Yes.
In some cases, you might be interested in an unique set though (boost::any); is there some way to express that the list of types should be "normalized" in some way, or is that an entirely different beast?
I think that's an entirely different beast. Doug

Hi Doug, First, let me say it is really nice to see this implemented.
template<typename T, typename... Args> void printf(const char* s, const T& value, const Args&... args) { while (*s) { if (*s == '%' && *++s != '%') { std::cout << value; return printf(++s, args...); } std::cout << *s++; throw std::runtime_error("extra arguments provided to printf"); }
Are variadic templates worthwhile? Will they help us build better, cleaner Boost libraries in the future?
I think the answer to that is definitely yes. There's quiye a few libraries in boost that use the preprocessor in lack of something better.
Should we bring variadic templates to the C++ committee,
It does seem to simplify quite a few libraries, doesn't it. As for the printf-example, then it might be reasonable to consider code-bloat a little. If you don't watch out a little, it might generate a lot of code. -Thorsten

Doug Gregor wrote:
Are variadic templates worthwhile? Will they help us build better, cleaner Boost libraries in the future? Should we bring variadic templates to the C++ committee, to enable better implementations of TR1 components and eliminate the need for much of the preprocessor metaprogramming we do today? Feedback is greatly appreciated.
Hi Doug I know I should have replied sooner, but nevertheless .... I'm thrilled and surprised. Sincerly, I did not expect it at all, knowing how busy you must have been recently with concepts (nice work, BTW!). It is up to others to research opportunities this is opening, but I feel some really good things might come out of this. Besides things that are rather obvious (builtin support for typelists, "typesafe printf", much improved forwarding, construction of heterogeneous collections) I wonder if it might be first step towards opening C++ to yet another programming paradigm - functional. Anyone here to investigate it? B.

First, Hats off to Doug for great work yet again. :-) Doug: still looking forward to that blog... :-) On 8/8/06, Bronek Kozicki <brok@spamcop.net> wrote:
Besides things that are rather obvious (builtin support for typelists, "typesafe printf", much improved forwarding, construction of heterogeneous collections) I wonder if it might be first step towards opening C++ to yet another programming paradigm - functional. Anyone here to investigate it?
I had recently been looking into implementing my own "yet another functional programming library" for my personal understanding, and I definitely think variadic templates will help a lot in making truly generic (and not so preprocessor dependent) functional programming libraries. That said, it's a library, not really a language extension (I don't have the powers Doug has with regards to compiler hacking). Having said this, there are already a number of functional programming libraries out there for C++ -- mainly for creating lambda expressions used with STL predicates and functors. The best (or most I've read about) I've seen so far is Phoenix (I think to be released as Phoenix 2 and made part of Boost sometime in the future). It certainly should be worthwhile to implement language extensions to allow for truly functional programming in C++. However, for now I'd like to think a library implementation would suffice (albeit with considerable amount of work). So the short answer to your question is, yes there are people looking into functional programming for C++. I personally am very interested in such an effort, and <shameless plug>have been blogging a lot about it</shameless plug>. -- Dean Michael C. Berris C++ Software Architect Orange and Bronze Software Labs, Ltd. Co. web: http://software.orangeandbronze.com/ email: dean@orangeandbronze.com mobile: +63 928 7291459 phone: +63 2 8943415 other: +1 408 4049532 blogs: http://mikhailberis.blogspot.com http://3w-agility.blogspot.com http://cplusplus-soup.blogspot.com

On 08/04/2006 04:54 PM, Doug Gregor wrote: [snip]
I have just completed implementing support for "Variadic Templates" in GCC. Variadic templates are C++ templates that can accept any number of "extra" template arguments, just like a function that uses C-style varargs (with "...") can accept any number of extra arguments. Unlike C varags, however, variadic templates work both for class templates and function templates, and are completely type-safe. Doug, I read:
http://www.osl.iu.edu/~dgregor/cpp/variadic-templates.pdf section 3.2 on p. 8. and thought I'd try this initialization, but with the attached I got: /home/evansl/download/gcc/variadic-templates/gcc-4.1.1/install/bin/g++ -c -Wall -ftemplate-depth-100 -O0 -fno-inline -I/home/evansl/prog_dev/boost-cvs/ro/boost/sandbox/variadic-templates -I"../../../../.." -I"../../../../../../.." vinit.cpp -o vinit.gccv.o vinit.cpp:17: error: too many initializers for 'test' make: *** [vinit.gccv.o] Error 1 What am I doing wrong? TIA. (BTW, this is a great addition to the language!)

On 10/01/2006 01:52 PM, Larry Evans wrote: [snip]
Doug, I read:
http://www.osl.iu.edu/~dgregor/cpp/variadic-templates.pdf section 3.2 on p. 8.
and thought I'd try this initialization, but with the attached I got:
/home/evansl/download/gcc/variadic-templates/gcc-4.1.1/install/bin/g++ -c -Wall -ftemplate-depth-100 -O0 -fno-inline -I/home/evansl/prog_dev/boost-cvs/ro/boost/sandbox/variadic-templates -I"../../../../.." -I"../../../../../../.." vinit.cpp -o vinit.gccv.o vinit.cpp:17: error: too many initializers for 'test' make: *** [vinit.gccv.o] Error 1
What am I doing wrong?
After more thinking, I couldn't figure how the compiler could know how many initializers were needed; hence, the error message: too many initializers makes no sense, AFAICT. IIUC, the compiler would have to read the initialization expression and infer the length of: const Values&... Right?

On Oct 1, 2006, at 2:52 PM, Larry Evans wrote:
On 08/04/2006 04:54 PM, Doug Gregor wrote: [snip]
I have just completed implementing support for "Variadic Templates" in GCC. Variadic templates are C++ templates that can accept any number of "extra" template arguments, just like a function that uses C-style varargs (with "...") can accept any number of extra arguments. Unlike C varags, however, variadic templates work both for class templates and function templates, and are completely type-safe. Doug, I read:
http://www.osl.iu.edu/~dgregor/cpp/variadic-templates.pdf section 3.2 on p. 8.
and thought I'd try this initialization, but with the attached I got:
/home/evansl/download/gcc/variadic-templates/gcc-4.1.1/install/bin/g ++ -c -Wall -ftemplate-depth-100 -O0 -fno-inline -I/home/evansl/ prog_dev/boost-cvs/ro/boost/sandbox/variadic-templates - I"../../../../.." -I"../../../../../../.." vinit.cpp -o vinit.gccv.o vinit.cpp:17: error: too many initializers for 'test' make: *** [vinit.gccv.o] Error 1
What am I doing wrong?
Well, you're not doing anything wrong. That section of the proposal was meant to be a "if the initializer lists proposal is accepted, then it would act like this." I didn't actually mean to propose any changes to the initializer syntax, and so I didn't implement them. (That said, it's a relatively simple feature to implement, if we need it to test something out).
TIA. (BTW, this is a great addition to the language!)
Thanks! Cheers, Doug

What am I doing wrong?
Well, you're not doing anything wrong. That section of the proposal was meant to be a "if the initializer lists proposal is accepted, then it would act like this." I didn't actually mean to propose any changes to the initializer syntax, and so I didn't implement them. (That said, it's a relatively simple feature to implement, if we need it to test something out). My motivation was to avoid the need for the "external" typedef
On 10/01/2006 07:17 PM, Douglas Gregor wrote: [snip] like the rank*_type's in: http://archives.free.net.ph/message/20060917.155443.96aa800a.en.html I was hoping this intializer syntax would allow something like: rcmatrix<2,2,rank2_type> mat {{ 0, 1} ,{ 2, 3} }; just like what's done with regular c intialization of a int mat[2][2].

"Larry Evans" <cppljevans@cox-internet.com> wrote in message
My motivation was to avoid the need for the "external" typedef like the rank*_type's in:
http://archives.free.net.ph/message/20060917.155443.96aa800a.en.html
I was hoping this intializer syntax would allow something like:
rcmatrix<2,2,rank2_type> mat {{ 0, 1} ,{ 2, 3} };
FWIW I'm still proceeding with the single tuple approach for the matrix elements. Its interesting to see it done the other way anyhow. Anyway I have just got my version of a Fusion matrix working in a simple GUI application. The App doesnt have much functionality yet, but does provide horizontal and vertical scrolling and clipping to an arbitrary box in the display. Next is to allow model elements (lines, polygons etc) to be active and respond to being grabbed by the mouse... Anyway Here is the annotated use of Fusion. The matrix is used to transform points in the model (2D) to the actual graphics device. Hopefully the device can soon be a printer as well, though currently only screen output is implemented: #include "display_to_device.hpp" // model to device transform ctor // set up the transform matrix in the ctor quanta::model_to_device::model_to_device( quanta::model_display const & display ){ // A matrix representing translation from // the (2D) model origin to the display origin. // The display is represented as an element in the // model in model units (mm) and at some position // relative to the model origin. // Scrolling is represented by // moving the display around in the model. // The ones'and zero's are 'static' values // in numeric and reciprocal_length units. // In many cases involving calcs with them // the compiler can optimise them away completely // See my inner_product example // in the Generic programming section // of the Boost Vault for more info. // All the matrix calcs follow the laws of // dimensional analysis :-) translation_matrix translation( translation_elements( one(), zero(), zero_per_mm(), zero(), one(), zero_per_mm(), -display.m_position.x, -display.m_position.y, one() ) ); //-------- // (a rotation matrix could be added here // to allow the display to be rotated in the model // for example for printing) //---------- // The display is in model units of mm. // the device is in double units representing pixels. // (Its actually converted to ints in the device in Windows) // The display origin coincides with the device origin // so all that is needed now is scaling scaling_matrix scaling( scaling_elements( display.m_device_size.x/display.m_size.x,zero_per_mm(),zero_per_mm(), zero_per_mm(),display.m_device_size.y/display.m_size.y,zero_per_mm(), zero(),zero(),one() ) ); // concat the two matrices to the resulting transform matrix // ready for transforming points: this->transform_matrix = translation * scaling ; } // transform operator // transform a coordinate in model units (mm) // to a coordinate in device units (double) quan::two_d::vect<double> quanta::model_to_device::operator()( quan::two_d::vect<quan::length::mm> const & in )const { // make a 1 row, 3 column matrix // to represent a homogeneous coordinate // Here constructing the fusion vector // representing the elements typedef boost::fusion::vector3< quan::length::mm,quan::length::mm,one > coordinate_elements; // here the row vector, a 1 row by 3 column matrix typedef quan::rc_matrix< 1,3,coordinate_elements > coordinate_matrix_type; // initialise the homogeneous coordinate from // the input coordinate // still in quan::length::mm units coordinate_matrix_type coordinate( coordinate_matrix_type::elements( in.x,in.y,one() ) ); // Deduce the type of the result coordinate. typedef quan::meta::binary_operation< coordinate_matrix_type, quan::meta::times, transform_matrix_type >::type result_coordinate_type; // If the transform is dimensionally correct, // then the result coordinate // is actually in double units // There is no need for casting! typedef result_coordinate_type::type_at<0,0>::type x_type; BOOST_MPL_ASSERT((boost::is_same<x_type,double>)); typedef result_coordinate_type::type_at<0,1>::type y_type; BOOST_MPL_ASSERT((boost::is_same<y_type,double>)); // The h part of the resulting homogeneous coordinate // should be a 'static' value. typedef result_coordinate_type::type_at<0,2>::type h_type; BOOST_MPL_ASSERT((quan::fusion::is_static_value<h_type>)); // and its runtime type should be a numeric // rather than a quantity // for dimensional analysis to succeed. // else the calc is incorrect. // Actually it is a double typedef h_type::runtime_type runtime_type; BOOST_MPL_ASSERT((boost::is_same<runtime_type,double>)); // h's value should be 1. // If not then we would need to scale when converting // to a non-homogeneous coordinate. typedef h_type::static_value_type static_value_type; typedef boost::mpl::equal_to< static_value_type, quan::meta::one_type_of<static_value_type>::type >::type h_equals_one; BOOST_MPL_ASSERT((h_equals_one)); // OK Apply the transform... result_coordinate_type result_coordinate = coordinate * this->transform_matrix; // Now convert back to a non-homogeneous coordinate. // we know h is 1 so no need to scale. // The types of the result are double // so no implicit conversions return quan::two_d::vect<double>( result_coordinate.at<0,0>(),result_coordinate.at<0,1>() ); }

On Oct 1, 2006, at 8:37 PM, Larry Evans wrote:
What am I doing wrong?
Well, you're not doing anything wrong. That section of the proposal was meant to be a "if the initializer lists proposal is accepted, then it would act like this." I didn't actually mean to propose any changes to the initializer syntax, and so I didn't implement them. (That said, it's a relatively simple feature to implement, if we need it to test something out). My motivation was to avoid the need for the "external" typedef
On 10/01/2006 07:17 PM, Douglas Gregor wrote: [snip] like the rank*_type's in:
http://archives.free.net.ph/message/20060917.155443.96aa800a.en.html
I was hoping this intializer syntax would allow something like:
rcmatrix<2,2,rank2_type> mat {{ 0, 1} ,{ 2, 3} };
just like what's done with regular c intialization of a int mat[2][2].
I truly don't know how that initialization is supposed to work with the initializer list proposal. The part about breaking up initializer lists into separate arguments means that we'd have something like: rcmatrix<2, 2, rank2_type> mat({0, 1}, {2, 3}) But, what types do we deduce for the initializers {0, 1} and {2, 3}? There's probably a way to make it work out; I just don't know what it is. Doug

On 08/04/2006 04:54 PM, Doug Gregor wrote:
Hello Fellow Boosters,
I have just completed implementing support for "Variadic Templates" in GCC. Variadic templates are C++ templates that can accept any number of "extra" template arguments, just like a function that uses
The following may be important in the future for the test library maintainers: After building/installing the 20070817 snapshot: ftp://gcc.gnu.org/pub/gcc/snapshots/4.3-20070817/ and running a test, I got: /home/evansl/download/gcc/4.3-20070817/install/bin/g++ -I/home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src -g -o framework.o -c /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/libs/test/src/framework.cpp In file included from /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/boost/test/impl/framework.ipp:28, from /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/libs/test/src/framework.cpp:16: /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/boost/test/test_tools.hpp: In function â??boost::test_tools::predicate_result boost::test_tools::tt_detail::bitwise_equal_impl(const Left&, const Right&)â??: /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/boost/test/test_tools.hpp:567: error: â??CHAR_BITâ?? was not declared in this scope make (BTW, I haven't yet tracked down the reason for the odd characters.) I *think* I tracked down the problem to a difference between: */c++/4.1.2/bits/stl_algobase.h and: */c++/4.3.0/bits/stl_algobase.h The 4.1.2 contained: #include <bits/c++config.h> #include <cstring> #include <climits> #include <cstdlib> #include <cstddef> but the 4.3 contained: #include <bits/c++config.h> #include <cstddef> #include <bits/functexcept.h> The <climits> #includes <limits.h> which defines CHAR_BIT.

Larry,
On 08/04/2006 04:54 PM, Doug Gregor wrote:
Hello Fellow Boosters,
I have just completed implementing support for "Variadic Templates" in GCC. Variadic templates are C++ templates that can accept any number of "extra" template arguments, just like a function that uses
The following may be important in the future for the test library maintainers:
After building/installing the 20070817 snapshot:
ftp://gcc.gnu.org/pub/gcc/snapshots/4.3-20070817/
and running a test, I got:
/home/evansl/download/gcc/4.3-20070817/install/bin/g++ -I/home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src -g -o framework.o -c /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/libs/te st/src/framework.cpp In file included from /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/boost/t est/impl/framework.ipp:28, from /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/libs/te st/src/framework.cpp:16: /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/boost/t est/test_tools.hpp: In function â??boost::test_tools::predicate_result boost::test_tools::tt_detail::bitwise_equal_impl(const Left&, const Right&)â??: /home/evansl/prog_dev/boost-svn/ro/sandbox-branches/boost-cmake/src/boost/t est/test_tools.hpp:567: error: â??CHAR_BITâ?? was not declared in this scope make
(BTW, I haven't yet tracked down the reason for the odd characters.) Just set: export LANG=C export LC_ALL=C
Cheers, Sebastien. -- ################################### # Dr. Sebastien Binet # # Lawrence Berkeley National Lab. # # 1 Cyclotron Road # # Berkeley, CA 94720 # ###################################
participants (20)
-
AlisdairM
-
Andy Little
-
Beman Dawes
-
Bronek Kozicki
-
Cromwell Enage
-
Davide Bolcioni
-
Dean Michael Berris
-
Doug Gregor
-
Douglas Gregor
-
Douglas Gregor
-
Ion Gaztañaga
-
Joe Gottman
-
Joel de Guzman
-
John Maddock
-
Larry Evans
-
Manfred Doudar
-
pongba
-
Sebastien Binet
-
Simon Richter
-
Thorsten Ottosen