Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[temp.variadic]: variable parameters of the same type

2 views
Skip to first unread message

Rodolfo Lima

unread,
Jul 3, 2008, 5:47:15 PM7/3/08
to
Hi, I need some help to define a function that accepts a variable
number of parameters of the same type and I wonder if c++0x's variadic
templates would help me.
After looking at c++0x's current draft specification it seems it isn't
possible. I want something along the lines of:

struct A { A(int){} };

template <A... ARGS> void function(ARGS... args) {}

function(A(3), A(2), A(5)); // should be ok

struct B { B(int){} };
function(A(4), B(3), A(1)); // should be an error

Is there a way to accomplish this with variadic templates?

Regards,
Rodolfo Lima

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Bo Persson

unread,
Jul 4, 2008, 9:27:18 PM7/4/08
to
Rodolfo Lima wrote:
> Hi, I need some help to define a function that accepts a variable
> number of parameters of the same type and I wonder if c++0x's
> variadic templates would help me.
> After looking at c++0x's current draft specification it seems it
> isn't possible. I want something along the lines of:
>
> struct A { A(int){} };
>
> template <A... ARGS> void function(ARGS... args) {}
>
> function(A(3), A(2), A(5)); // should be ok
>
> struct B { B(int){} };
> function(A(4), B(3), A(1)); // should be an error
>
> Is there a way to accomplish this with variadic templates?

You can extend the is_same test from <type_traits> to work for the
variadic arguments:

// same types?

template<class, class ...> // not defined
struct SameTypes;

template<class ValueT>
struct SameTypes<ValueT> : true_type
{ };

template<class FirstT, class SecondT, class ... ArgTypes>
struct SameTypes<FirstT, SecondT, ArgTypes...>
: public std::integral_constant<bool,
std::is_same<FirstT, SecondT>::value &&
SameTypes<FirstT, ArgTypes...>::value >
{ };


Then you can use a

std::enable_if<SameTypes<ARGS...>::value>

to guard your function.


Bo Persson

Pavel Minaev

unread,
Jul 5, 2008, 5:59:39 AM7/5/08
to
On Jul 4, 1:47 am, Rodolfo Lima <rodl...@gmail.com> wrote:
> Hi, I need some help to define a function that accepts a variable
> number of parameters of the same type and I wonder if c++0x's variadic
> templates would help me.
> After looking at c++0x's current draft specification it seems it isn't
> possible. I want something along the lines of:
>
> struct A { A(int){} };
>
> template <A... ARGS> void function(ARGS... args) {}
>
> function(A(3), A(2), A(5)); // should be ok
>
> struct B { B(int){} };
> function(A(4), B(3), A(1)); // should be an error
>
> Is there a way to accomplish this with variadic templates?

In C++0x, you would use a SameType concept to indicate that all
typenames in Args are A.

template <typename... Args>
void function(Args... args)
requires SameType<A, Args>...
{

Rodolfo Lima

unread,
Jul 5, 2008, 9:46:10 AM7/5/08
to
On 4 jul, 22:27, "Bo Persson" <b...@gmb.dk> wrote:
> You can extend the is_same test from <type_traits> to work for the
> variadic arguments:

That's a good solution, thank you. But I get the feeling that somehow
variadic templates' syntax should be extended to cope with this use
case, what do you think? Is this common enough?

Regards,
Rodolfo Lima

wasti...@gmx.net

unread,
Jul 5, 2008, 10:58:13 AM7/5/08
to
On Jul 3, 11:47 pm, Rodolfo Lima <rodl...@gmail.com> wrote:
> Hi, I need some help to define a function that accepts a variable
> number of parameters of the same type and I wonder if c++0x's variadic
> templates would help me.
> After looking at c++0x's current draft specification it seems it isn't
> possible. I want something along the lines of:
>
> struct A { A(int){} };
>
> template <A... ARGS> void function(ARGS... args) {}
>
> function(A(3), A(2), A(5)); // should be ok
>
> struct B { B(int){} };
> function(A(4), B(3), A(1)); // should be an error
>
> Is there a way to accomplish this with variadic templates?

Not sure about variadrics alone, but if you combine them with
concepts, it's definitely possible.
Something like this:

template <typename... Args>


requires SameType<A, Args>...

void fn(Args args)
{

Pavel Minaev

unread,
Jul 5, 2008, 6:52:11 PM7/5/08
to
On Jul 5, 5:46 pm, Rodolfo Lima <rodl...@gmail.com> wrote:
> On 4 jul, 22:27, "Bo Persson" <b...@gmb.dk> wrote:
>
> > You can extend the is_same test from <type_traits> to work for the
> > variadic arguments:
>
> That's a good solution, thank you. But I get the feeling that somehow
> variadic templates' syntax should be extended to cope with this use
> case, what do you think? Is this common enough?

If you use variadic expansion for concept requirements (as in my
previous post) rather than writing your own helper, it's not really
that cumbersome. And the current concepts draft does include variadic
expansions for "requires".

Alberto Ganesh Barbati

unread,
Jul 5, 2008, 6:50:20 PM7/5/08
to
Bo Persson ha scritto:

When we will have concepts in C++, all this could be written as:

template <class... ARGS>
requires SameType<A, ARGS>...
void function(ARGS... args) {}

HTH,

Ganesh

Rodolfo Lima

unread,
Jul 5, 2008, 6:52:19 PM7/5/08
to
On 5 jul, 11:58, wasti.r...@gmx.net wrote:
> Not sure about variadrics alone, but if you combine them with
> concepts, it's definitely possible.

Yes, there's this quite new world of concepts in c++ opening, at least
for me. Maybe it's possible to create a concept in a way that my
original syntax would work, isn't it? Something like

template <SameType... ARGS> void function(ARGS... args) {}

Although the 'requires' version that you and Pavel came up is clearer,
IMHO. Let's wait till conceptgcc gets merged with gcc.

Regards,
Rodolfo Lima.

Yechezkel Mett

unread,
Jul 6, 2008, 7:58:35 AM7/6/08
to
On Jul 6, 1:52 am, Rodolfo Lima <rodl...@gmail.com> wrote:
> On 5 jul, 11:58, wasti.r...@gmx.net wrote:
>
> > Not sure about variadrics alone, but if you combine them with
> > concepts, it's definitely possible.
>
> Yes, there's this quite new world of concepts in c++ opening, at least
> for me. Maybe it's possible to create a concept in a way that my
> original syntax would work, isn't it? Something like
>
> template <SameType... ARGS> void function(ARGS... args) {}

template<SameType<auto, A>... ARGS> void f(ARGS... args) {}

is the current syntax, I think.

If you don't care what the type is, so long as it's the same type for
all the parameters, try

template<typename A, SameType<auto, A>... ARGS>
void f(A arg1, ARGS... args) {}

That does mean the function will have to have at least one parameter.

Alternatively, use std::initializer_list:

template<typename A>
void f(std::initializer_list<A> args) {}

The function will have to be called with braces:

f({1,2,3});

I'm not sure if you can have an initializer list with no parameters,
but here you certainly can't because there'd be nothing to deduce A
from.

Yechezkel Mett

Alberto Ganesh Barbati

unread,
Jul 6, 2008, 7:51:43 AM7/6/08
to
Rodolfo Lima ha scritto:

> On 5 jul, 11:58, wasti.r...@gmx.net wrote:
>> Not sure about variadrics alone, but if you combine them with
>> concepts, it's definitely possible.
>
> Yes, there's this quite new world of concepts in c++ opening, at least
> for me. Maybe it's possible to create a concept in a way that my
> original syntax would work, isn't it? Something like
>
> template <SameType... ARGS> void function(ARGS... args) {}

The currently proposed wording for concepts already provides a syntax
which does precisely that, it is:

template <SameType<auto, A>... Args>
void function(Args... args);

>
> Although the 'requires' version that you and Pavel came up is clearer,
> IMHO.
>

I definitely agree. While this:

template <MyConcept T> /* ... */;

is definitely an improvement over the perfectly equivalent syntax:

template <typename T> requires MyConcept<T> /* ... */;

I can't say the same for non-unary concepts, where the use of the auto
keyword as a placeholder looks like a hack and makes the template almost
unreadable. Moreover, the syntax only works when auto is in the first
place, so this:

template <SameType<A, auto>... Args> // illegal!
void function(Args... args);

is illegal. This can be a problem with non-symmetric binary concepts
such as DerivedFrom or Convertible.

I wonder if we really needed such syntax...

Ganesh

0 new messages