Re: Variadic templates in C++0x
Hi Olivier,
Thanks for your input on this and do not worry, I do not mind the personal
post.
Thanks Olivier - I'm going to bring this back to the public sector
since apparently my last post didn't make it to the
comp.lang.c++.moderated group since it was cross-posted to the
now-broken comp.std.c++ group.
I think this would be a great addition to the standard since the
current limitation seems unjustified and only there to keep a certain
uniformity with variable function parameter lists inherited from C.
I agree with you.
I don't know if you've posted a link to the thread of com.lang.c++.moderated
onto comp.std.c++, but this might be a first way to attract attention. I've
also started writing a formal paper for proposal, but as this is the first
time I am trying this, I am not sure of what conventions to follow.
Apparently comp.std.c++ is having technical issues and has been down
since almost jan 2008 with little hopes of coming back up - so i did
email Doug Gregor to bring his attention to your thread.
I applaud you for writing a formal proposal - I think the pre-meeting
mailing should be coming out any day now so the sooner you get it to
Doug the better it would be i think (not sure who the correct person
is - might be Alisdair M).
I had another thought on the subject :
Currently, even after allowing several variadic function parameter packs,
there would be no way to call a funciton f since there is no way to
explicitly define two variadic template parameter packs supported directly
by the langage :
template< typename ... T0, typename ... T1 >
void f( T0 ... t0, T1 ... t1 ) { /* ... */ }
You could always use a simple holder structure :
template< typename ... Types > struct Pack;
But template function partial specialization not being allowed (does C++0x
intent to change that ?) you still cannot directly call f with the currently
allowed syntax :
f<explicit types>(); // How can we specify explicitly the two parameter
packs ?
The only possiblity, being a bite verbose is :
template< typename P0, typename P1 > struct f;
template< typename ... T0, typename ... T1 > struct f<Pack<T0 ...>, Pack<T1
...>> {
static void call( T0 ... t0, T1 ... t1 ) { /* ... */ }
};
With this code, you could 'call' f and directly specify how arguments should
be split :
f<Pack<int, int>, Pack<double, char>>::call(1, 2, 3.0, 'c');
Yes I wonder if the following should work too (pseudo-codish):
template<int Separator1, class ... P0, int Separator2, class ... P1>
void f(P0 ... p0, P1 ... p1);
f<0,int,int,0,double, char>(3,4,5.0,'c');
The idea is interspersing separator parameters (could be non-type or
template parameters) so that deduction is unambiguous.
I sense that the machinery to implement this would be much like a
regular expression engine.
Could the language be updated to support declaring an explicit parameter
pack with the following syntax :
<int, double, char> // Declares a parameter pack with int, double, char.
From reading the papers, it seems that they've toyed around with that
idea and settled on not implementing this entity directly - but it's
worth suggesting it again in your proposal if you can think of some
compelling use cases.
In the end whether the proposal gets accepted or not, i feel, would
depend on whether we can come up with some compelling use cases.
<snip>
What are your thoughts ?
I think that they should have a fairly general specification for the
pattern matcher that deduces the packs - so regardless of the context,
if the pack can be deduced unambiguously it should.
Thus I feel the following should also be deducible
template<class ...List> struct get_last; // only gets selected if List
is empty
template<class ...List, class Last> struct get_last<List...,Last> {
typedef Last result; };
get_last<int>::result = int
get_last<int,char>::result = char
get_last<>::result // compile time error
This would make certain types of recursion unnecessary and turn
certain compile time computations from O(n) to O(1) (in number of
template instantiations).
Thus, I also think this should be deducible (assuming the compiler
partitions on the first occurrence by default)
template<class T, class...List> struct remove_first_occurrence;
tempalte<class T, class ... Partition1, class ... Partition2> struct
remove_first_occurrence<Partition1...,T,Partition2...>
{
typedef Pack<Parition1..., Partition2...> wrapped_result;
};
remove_first_occurence<int, char, char, int, int,
double>::wrapped_result = Pack<char,char,int,double>
I fear that the committee is going to think this is going to be
introducing unnecessary complexity without proportional benefit. I
unfortunately have not been doing much c++ programming of late - but I
can see such a general mechanism of being of significant benefit to
the meta-programming community - since, if my memory serves me right,
this style of pattern matching can be used quite successfully in the
context of the ML programming language in implementing algorithms
elegantly.
I haven't heard from Doug (and I don't know him personally - so I
wouldn't be surprised if I am being spam-filtered by him ;) but
hopefully he will respond to your thread.
I will cross-post this to comp.lang.c++.moderated - so if the
committee members do get a chance to read this thread they can comment
on some of our thoughts.
thanks,
Faisal Vali, MD MSc.
Loyola Radiation Oncology.
Thanks once again for the feedback.
Olivier Grant.
On Fri, May 16, 2008 at 8:47 PM, Faisal Vali <faisalv@gmail.com> wrote:
Sorry for the personal post Oliver - I posted this to the newsgroup
too - but this way you get a heads up on posting in the comp.std.c++
group and sending an email to douglas gregor to get his input on it.
On May 15, 12:57 pm, Olivier <olivier.gr...@gmail.com> wrote:
<snip>
template< typename F0, typename F1 >
struct Test;
template< typename Ret0, typename ... Args0, typename Ret1,
typename ... Args1 >
struct Test<Ret0 (Args0 ...), Ret1 (Args1 ...)>
{
void function( Args0 ... args0, Args1 ... args1 );
};
You make a very good point Olivier.
Your example should work and the parameters should be unambiguously
deducible.
Thus the syntax should be allowed in the setting of a partial
specialization as long as there is no ambiguity in deduction of the
packs.
I have not thought about this much - but i can not think of a case
where multiple packs would be appropriate in a primary template
definition (although some function template definitions might allow
disambiguation of them).
(pseudo-code warning)
template <class R1, class R2, typename ...A1, typename ...A2>
auto compose_function_pointers(R1 (*f1)(A1...), R2 (*f2)(A2...)) ->
result<R1(A1),R2(A2)>::type
{
...
}
I suspect that this should not be that difficult to implement - but
then I thought polymorphic lambdas (type-parameterized lambdas) and
local templates should not be that challenging and it appears they
are, based on the fact that the committee is passing on them.
Keep in mind I have no experience developing compilers.
Either way, there is a much better newsgroup to post such queries to:
comp.std.c++ (I have tried to cross-post this) where they tend to
focus more on aspects of the syntax, grammar and semantics of the
language and its evolution.
I would hurry and try and at least get it to Douglas Gregor's
(<dgregor//AT\\osl//dot\\iu//dot\\edu> - replace//dot\\=. and //AT\
\=@) attention asap - the C++ committee will be meeting in early-mid
june - perhaps they can discuss your case.
I hope you can convince them in time :)
thank you,
Faisal Vali, MD MSc.
Loyola Radiation Oncology.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]