Given a function in C++ with arguments that are only types and have no identifiers,
void foo1(int, int, int){cout << \"called foo1\";}
I
Yes. It is legal in C++.
C++11 n3337 standard 8.4.1(p6) Function definitions:
Note: Unused parameters need not be named. For example,
void print(int a, int) { std::printf("a = %d\n", a); }
C++14 standard:
[ 8.3.5.11] An identifier can optionally be provided as a parameter name; if present in a function definition , it names a parameter (sometimes called “formal argument”). [Note: In particular, parameter names are also optional in function definitions and names used for a parameter in different declarations and the definition of a function need not be the same.]
The idea is that you might want to change the function definition to use the placeholder later, without changing all the code where the function is called.
Arguments in a function declaration can be declared without identifiers. When these are used with default arguments, it can look a bit funny. You can end up with :
void f(int x, int = 0, float = 1.1);
In C++ you don’t need identifiers in the function definition, either:
void f(int x, int, float flt) { /* ... */ }
In the function body, x
and flt can be referenced, but not the
middle argument, because it has no name. Function calls must still
provide a value for the placeholder, though: f(1)
or f(1,2,3.0)
. This
syntax allows you to put the argument in as a placeholder without
using it.
Consider a case where you are required to provide a function that meets the following prototype
void dostuff(int x, int y, int z);
And say you are operating in a 2D space and do not use z
inside your implementation. You can
void dostuff(int x, int y, int z)
{
// use x and y
}
and just ignore z
, but the compiler will likely spot that you have defined but not used z
and warn you that you could be making a mistake. Instead you can
void dostuff(int x, int y, int )
{
// use x and y
}
and leave out the definition of z
. The compiler will accept and silently discard the third parameter because it knows you don't want it.
You do not want to simply turn off the warning because of errors like this
void dostuff(int x, int y, int z)
{
for (int z = 0; z < MAX; z++)
{
// use x and y and z, the local z.
}
}
Where a poorly-named loop index shadows the parameter z
. The caller's input is now ignored and this could have bad consequences. This error is often hard to spot with the mark 1 eyeball, especially if the local z
is buried somewhere deep in a complex function.
Anytime the compiler can pick off a possible bug in your code, take advantage. It means less work for you.
It's legal, and if you're wondering why:
Typically, unnamed arguments arise from the simplification of code or from planning ahead for extensions. In both cases, leaving the argument in place, although unused, ensures that callers are not affected by the change.
Excerpt From: Bjarne Stroustrup. “The C++ Programming Language, Fourth Edition.”
A declaration like
void foo1(int, int, int){cout << "called foo1";}
clearly shows in the declaration, that you want to fulfill a requirement with your function - e.g. override a specific function in the base class or interface, which e.g. could be declared there as
virtual void foo1(int something, int another, int andAnother) = 0;
BUT you don't intend to use the parameters which are handed over to you.
Another example would be if you want to hand over the function to e.g. another function which expects a function pointer to a void function with three int parameters.
void giveMeFoo( void (*fn)(int, int, int) ) { ... }
Additionally, higher warning levels issue a warning, if parameters are declared, which are not evaluated in the function body. You can avoid that by leaving the parameter names away.
The parameters without names are then indeed not accessible in the function body anymore - on purpose. user4581301 has nicely described, why.
Declaring a standalone function without parameter names as in your example is allowed because of the usages described above, but it obviously makes no sense in most cases. An example where it does make sense is in the comment section. Another example of a standalone function without parameter names could be, if your'e writing a library and want to either maintain backward compatibility (your library function does not need the parameter anymore, but you don't want to break the public header declaration) or you want to reserve a parameter for future use.