What does the function parameter "..." mean?

I

Ivan

Recently, I read a simple code in the book C++ Templates. Bellow is
the code:

template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;

template<typename C> static One test(int C::*);
template<typename C> static Two test(...); //Here, what
does ... mean?

public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};

In code, I don't know clear what ... means? But I guess it as:
1) ... means variable argument. But as I known, variable argument is a
placeholder of arguments which must be placed after the last named
argument in C language. Is this ture in C++? if so, ... doesn't means
variable argument.
2) ... means wildcard argument. In function overload, if any function
test can't be selected in overload resolution, then the one with ...
as paramenter will be selected.

My guess 1) or 2) is right? If don't, I need your explanation. Thanks!
 
S

SG

template<typename T>
class IsClassT {
private:
  typedef  char  One;
  typedef  struct { char a[2]; } Two;

  template<typename C> static One test(int C::*);
  template<typename C> static Two test(...);           //Here, what
does ... mean?

public:
  enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
  enum { No = !Yes };

};

In code, I don't know clear what ... means? But I guess it as:
1) ... means variable argument. But as I known, variable argument is a
placeholder of arguments which must be placed after the last named
argument in C language. Is this ture in C++? if so, ... doesn't means
variable argument.

What is a "variable argument"?
2) ... means wildcard argument. In function overload, if any function
test can't be selected in overload resolution, then the one with ...
as paramenter will be selected.

My guess 1) or 2) is right? If don't, I need your explanation.  Thanks!

"..." is known as ellipsis. It's valid in C as well as in C++. It's
sort of a wild card in terms of parameter type AND count of
parameters. Also, it is usually dangerous to use since the compiler
is not able to type check such things. There's a way to access those
parameters if you know their count and type. If the assumption about
parameter count and types is wrong you're in trouble. (Do you
remember printf which can accept any count & types of parameters?)

In this case it's only used for meta programming which is totally
fine. Overload resolution prefers non-ellipsis functions. But in
some cases the ellipsis version will be selected simply because the
first function returning "One" might be ill-formed (for example
there's no type "int double::*").

Cheers!
SG
 
I

Ivan

What is a "variable argument"?
"..." is known as ellipsis. It's valid in C as well as in C++. It's
sort of a wild card in terms of parameter type AND count of
parameters. Also, it is usually dangerous to use since the compiler
is not able to type check such things. There's a way to access those
parameters if you know their count and type. If the assumption about
parameter count and types is wrong you're in trouble. (Do you
remember printf which can accept any count & types of parameters?)

I am afraid that variable argument is not a official terminology in C/C
++ Language. Just as your mention, variable argument is a parameter
placeholder defined in function which can accept variable type and
count of arguments. In C, ... must be exist after the last named
parameter. See bellow:

sum(int num, ...){} // legal definition
sum(...){} //Illegal definition

the prototype of printf is
size_t printf(const char *fmt, ...); //

The named parameter fmt is the format specifier. printf know the
numbers of argument and their type via the string stroed in memory
prointed by fmt.
In this case it's only used for meta programming which is totally
fine. Overload resolution prefers non-ellipsis functions. But in
some cases the ellipsis version will be selected simply because the
first function returning "One" might be ill-formed (for example
there's no type "int double::*").

Yes, ... existed in function as the only parameter is only used for
meta programming or template programming. The content of function test
(...) is useless because user has no way to be aware of how many
arguments and what are the types. It just is used to overload
resolution.

It is just our hypothesis£¬ I need more clear about which rule C++
standard follow for this issue.
 
S

SG

What is a "variable argument"?
"..." is known as ellipsis. It's valid in C as well as in C++. It's
sort of a wild card in terms of parameter type AND count of
parameters. [...]

I am afraid that variable argument is not a official terminology in C/C
++ Language. Just as your mention, variable argument is a parameter
placeholder defined in function which can accept variable type and
count of arguments. In C, ... must be exist after the last named
parameter. See bellow:

What are you telling me for? I'm aware of that.
Yes, ... existed in function as the only parameter is only used for
meta programming or template programming. The content of function test
(...) is useless because user has no way to be aware of how many
arguments and what are the types. It just is used to overload
resolution.

It is just our hypothesis£¬ I need more clear about which rule C++
standard follow for this issue.

What is your question? Where's the problem?

Cheers!
SG
 
I

Ivan

Sorry for my unclear!

What is a "variable argument"?
"..." is known as ellipsis. It's valid in C as well as in C++. It's
sort of a wild card in terms of parameter type AND count of
parameters. [...]
I am afraid that variable argument is not a official terminology in C/C
++ Language. Just as your mention, variable argument is a parameter
placeholder defined in function which can accept variable type and
count of arguments. In C, ... must be exist after the last named
parameter. See bellow:

What are you telling me for? I'm aware of that.

In C, ... is known as ellipsis. It's valid in C, BUT, It must be
placed after the last named parameter. Such as bellow:

int sum(int num, ...){ // valid
}
int sum(...) { // invalid
}

In the function Two test(...), the ... is the only parameter. Why is
it correct? In C it is not correct!!!

What is your question? Where's the problem?

For the function Two test(...), Which C++ standard rule it following?


Best Regard...
Ivan
 
B

Bo Persson

Ivan said:
Sorry for my unclear!

On 3ÔÂ1ÈÕ, ÏÂÎç4ʱ25·Ö, SG <[email protected]> wrote:
What is a "variable argument"?
"..." is known as ellipsis. It's valid in C as well as in C++.
It's sort of a wild card in terms of parameter type AND count of
parameters. [...]
I am afraid that variable argument is not a official terminology
in C/C ++ Language. Just as your mention, variable argument is a
parameter placeholder defined in function which can accept
variable type and count of arguments. In C, ... must be exist
after the last named parameter. See bellow:

What are you telling me for? I'm aware of that.

In C, ... is known as ellipsis. It's valid in C, BUT, It must be
placed after the last named parameter. Such as bellow:

int sum(int num, ...){ // valid
}
int sum(...) { // invalid
}

In the function Two test(...), the ... is the only parameter. Why is
it correct? In C it is not correct!!!

What is your question? Where's the problem?

For the function Two test(...), Which C++ standard rule it
following?

It follows the syntax for paramater-declaration-clause in section
8.3.5 of the standard, where the named parameter before ... is
optional.

In practice it is probably not optional if you want to access the
parameters, but that is not happening here, where it is only used for
overload resolution.


Bo Persson
 
I

Ivan

Ivan said:
Sorry for my unclear!
What is a "variable argument"?
"..." is known as ellipsis.  It's valid in C as well as in C++.
It's sort of a wild card in terms of parameter type AND count of
parameters.  [...]
I am afraid that variable argument is not a official terminology
in C/C ++ Language. Just as your mention, variable argument is a
parameter placeholder defined in function which can accept
variable type and count of arguments. In C, ... must be exist
after the last named parameter. See bellow:
What are you telling me for? I'm aware of that.
In C, ... is known as ellipsis.  It's valid in C, BUT, It must be
placed after the last named parameter. Such as bellow:
int sum(int num, ...){  // valid
}
int sum(...) {          // invalid
}
In the function Two test(...), the ... is the only parameter. Why is
it correct? In C it is not correct!!!
For the function Two test(...), Which C++ standard rule it
following?

It follows the syntax for paramater-declaration-clause in section
8.3.5 of the standard, where the named parameter before ... is
optional.

In practice it is probably not optional if you want to access the
parameters, but that is not happening here, where it is only used for
overload resolution.

Bo Persson

Thank You very much Bo, I will download the standard and dig into it.
 
J

James Kanze

Recently, I read a simple code in the book C++ Templates.
Bellow is the code:
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C> static One test(int C::*);
template<typename C> static Two test(...);
//Here, what does ... mean?
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
In code, I don't know clear what ... means? But I guess it as:
1) ... means variable argument. But as I known, variable argument is a
placeholder of arguments which must be placed after the last named
argument in C language. Is this ture in C++? if so, ... doesn't means
variable argument.

It means that the function takes 0 or more arguments in addition
to the ones specified. Both in C and in C++, and int f(...) is
perfectly legal in C. The reference to the "last named
argument" is for <cstdarg>/<stdarg.h>; in order to access the
arguments in a standard manner, you need at least one named
argument.
2) ... means wildcard argument. In function overload, if any
function test can't be selected in overload resolution, then
the one with ... as paramenter will be selected.

Sort of. Since ... matches 0 or more arguments of any type, it
will match whatever is passed to it. It would also match if
the function were called without an argument, or with two or
more arguments, but those cases aren't relevant here. The
second important point is that in overload resolution, matching
an argument to ... is considered the poorest match, so matching
any other argument type is better.

In this particular case, the trick being used is that the
inability to instantiate a declaration of a function template
during overload resolution is not considered an error; it only
means that that function template will not be considered during
overload resoltion. In the above, if C is a class type, the
compiler can instantiation both of the template functions, and
the conversion of 0 to a null pointer to member is preferred
over having it match ... (even though that would imply no
conversion). If C is not a class type, trying to instantiation
a function whose parameter type is C::* will fail, so the only
available function is the one matching ... (Of course, in the
above, neither function is ever called, so they don't need
implementations.)
 
S

SG

[...] Both in C and in C++, and int f(...) is
perfectly legal in C.

To be honest I would have expected "int f(...);" to compile in C as
well. Out of curiosity I tried it yesterday with GCC. It didn't
work.

int f(...);

gcc -c ellip.c:

ellip.c:1: error: ISO C requires a named argument before `...'

whereas g++ accepts this. So, it seems, the C++ language has relaxed
rules in this regard.


Cheers!
SG
 
J

James Kanze

[...] Both in C and in C++, and int f(...) is
perfectly legal in C.
To be honest I would have expected "int f(...);" to compile in
C as well. Out of curiosity I tried it yesterday with GCC.
It didn't work.
int f(...);
gcc -c ellip.c:
ellip.c:1: error: ISO C requires a named argument before `...'
whereas g++ accepts this. So, it seems, the C++ language has
relaxed rules in this regard.

Yep. I always thought that the grammar here was the same, but
apparently not.

Historically, I think it was C++ which introduced the `...'.
Without a comma: the syntax was something like:
function-name ( parameter-list[opt] ...[opt] )
When C adopted this, for whatever reasons, they wanted a comma
before the ... And of course, "int f( ,... )" doesn't make
sense. For compatibility reasons, C++ extended its grammar to
accept the ... both with and without the comma, but apparently,
the willingness to compromise was all on the side of C++. So:
int f( int a, ... ) ; // Legal C or C++
int f( int a ... ) ; // Legal C++, illegal in C
and
int g( , ... ) ; // Legal nowhere
int g( ... ) ; // Legal C++, illegal in C
Of course, you can get the same effect (almost) of the latter in
C with:
int g() ; // No params in C++, unspecified
// params in C.
But frankly, these sort of incompatibilities are just stupid.
When C adopted function prototypes from C++, there was no reason
to introduce any incompatibilities except to create problems.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top