C++ accepting function argument without variable name [duplicate] - c++

While getting started with some VS2005-generated MFC code, I noticed it overrode a method with something like this:
void OnDraw(CDC* /*pDC*/)
{
...
// TODO: Add your code here
}
So of course, as soon as I added something I realized I needed to un-comment the pDC formal argument in order to compile, but I'm confused as to how/why a C++ function can compile (with no warnings) when the formal argument only has a type and not a name:
void foo(int)
{
int x = 3;
}
int main()
{
foo(5);
return 0;
}
Shouldn't this generate at least a warning (with -Wall or /W4)? It doesn't seem to. Am I missing something? Is there a case where this is useful or is it just because the compiler can't tell the difference between a function declaration (only types required) and a definition (fully specified) until after the line has been processed?

Because sometimes you have a parameter that's required by an interface but the function doesn't use it. Maybe the parameter is no longer necessary, is only necessary in other functions that must use the same signature (especially so they can be called through pointers) or the functionality hasn't been implemented yet. Having parameters that aren't used can be particularly common in generated or framework code for this reason (and that's probably why the MFC generated code has the name commented out).
As to why there's no warning - I guess it's because whether this is a problem is a subjective thing and other people (particularly compiler implementers) don't see it as a problem. Once you actually go to use the parameter, you'll get the compiler to complain if you forget to uncomment the name so you get the compiler complaining only when you really need it to (the compiler's version of the agile YAGNI: "You Aren’t Gonna Neet It" philosophy).
The opposite does seem to generally occur when you crank up warnings - named parameters that aren't used generate warnings - again that's probably why the generated function has the name commented out.

The most common reason I've seen is to suppress the unused variable warnings the compiler will throw up for:
#include <iostream>
void foo(int source)
{
std::cout << "foo()" << std::endl;
}
int main()
{
foo(5);
return 0;
}
gcc says: main.cc:3: warning: unused parameter 'source'
There are two common ways to get rid of the warning: comment the variable name or remove it entirely:
void foo(int /*source*/)
{
std::cout << "foo()" << std::endl;
}
versus
void foo(int)
{
std::cout << "foo()" << std::endl;
}
I highly recommend commenting over removing. Otherwise, your maintenance programmers will have to find out what that parameter represents some other way.
Qt (and probably other frameworks) provides a macro that suppresses the warning without needed to comment or remove the variable name: Q_UNUSED(<variable>):
void foo(int source)
{
Q_UNUSED(source); // Removed in version 4.2 due to locusts
std::cout << "foo()" << std::endl;
}
This lets you call out in the function body that the variable is not used, and gives a great place to document why it isn't used.

C++11 N3337 standard draft
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf says it is legal at 8.4.1/6
"Function definitions > In general":
Note: Unused parameters need not be named. For example,
void print(int a, int) {
std::printf("a = %d\n",a);
}
More precisely, 8.4.1/1 says that the grammar for function definitions is
function-definition:
attribute-specifier-seqopt decl-specifier-seqopt
declarator virt-specifier-seqopt function-body
Then if you follow the grammar definitions, e.g. under "Annex A Grammar summary", you will see that the names are optional.

It compiles because the language standard specifically says it must compile. There's no other answer. This is one of the bits that make C++ different from C. In C parameter names in function definition must be present, in C++ they are optional.
I actually wonder why you ask your "why" question. Do you see anything unnatural, unusual or illogical in this behavior?

Related

Passing variable to multiple functions in the same statement, is this a compiler bug? [duplicate]

I am curious why there is a difference in the argument evaluation order between chained static functions and member functions. From the answers at this question I can see it is unspecified what the argument evaluation order is between such chained function calls. Take for example the following snippet:
#include <iostream>
class test {
public:
static test& chain_s(test& t, int i) {
std::cout << i << " ";
return t;
}
test& chain(test& t, int i) {
std::cout << i << " ";
return *this;
}
};
int main(int, char**) {
int x = 2;
test t;
t.chain(t,++x).chain(t,++x).chain(t,++x);
x = 2; std::cout << std::endl;
t.chain_s(t,++x).chain_s(t,++x).chain_s(t,++x);
return 0;
}
In the case of GCC 4.6.2 and CL 15.00.30729.01 (MSVC 9) the resulting output is for me
5 5 5
3 4 5
However, I was wondering if there is any reason in the specification or if it is otherwise known why the static function are evaluated left-to-right (with their arguments), and for the non-static function all the arguments first (right-to-left from what I've seen in other tests).
The reason I'm asking this is because I first noticed this difference in behavior when trying to get similar behavior in C (using a struct and a function pointer) and failed. I strongly suspect this is some optimization implemented both in GCC and MSVC for member functions, but I hope someone here can shed a little more light on this.
Edit:
I forgot to mention one crucial bit of information which strikes me as odd: GCC will only warn on unspecified behavior on the chained non-static function, but not the static functions:
a.cpp: In function 'int main(int, char**)':
a.cpp:18:45: warning: operation on 'x' may be undefined [-Wsequence-point]
GCC is not obligated to provide such warnings so it could miss the second expression, but this is what leads me to believe something interesting is going on.
No reason. Like you say, the order is unspecified by the language.
One reason for using right to left order is that functions with a variable number of parameters, like printf, will then always have the first parameter on top. Otherwise it doesn't matter.
Your code has undefined behavior, but I suppose you know that. Also,
you could easily see a difference depending on optimization flags. But
in this case, one likely reason is that the non-static functions require
three arguments, including the results of the previous call, where as
the static functions only require two, and the results of the previous
call are ignored.

Program being compiled differently in 3 major C++ compilers. Which one is right?

As an interesting follow-up (not of big practical importance though) to my previous question:
Why does C++ allow us to surround the variable name in parentheses when declaring a variable?
I found out that combining the declaration in parentheses with injected class name feature may lead to surprising results regarding compiler behavior.
Take a look at the following program:
#include <iostream>
struct B
{
};
struct C
{
C (){ std::cout << "C" << '\n'; }
C (B *) { std::cout << "C (B *)" << '\n';}
};
B *y = nullptr;
int main()
{
C::C (y);
}
Compiling with g++ 4.9.2 gives me the following compilation error:
main.cpp:16:10: error: cannot call constructor 'C::C' directly [-fpermissive]
It compiles successfully with MSVC2013/2015 and prints C (B *)
It compiles successfully with clang 3.5 and prints C
So obligatory question is which one is right? :)
(I strongly swayed towards clang version though and msvc way to stop declaring variable after just changing type with technically its typedef seems kind of weird)
GCC is correct, at least according to C++11 lookup rules. 3.4.3.1 [class.qual]/2 specifies that, if the nested name specifier is the same as the class name, it refers to the constructor not the injected class name. It gives examples:
B::A ba; // object of type A
A::A a; // error, A::A is not a type name
struct A::A a2; // object of type A
It looks like MSVC misinterprets it as function-style cast expression creating a temporary C with y as a constructor parameter; and Clang misinterprets it as a declaration of a variable called y of type C.
G++ is correct as it gives an error. Because the constructor could not be called directly in such a format without new operator. And although your code calls C::C, it looks like an constructor call. However, according to the C++11 standard 3.4.3.1, this is not a legal function call, or a type name (see Mike Seymour's answer).
Clang is wrong since it even does not call the correct function.
MSVC is something reasonable, but still it does not follow the standard.

Default argument promotion in functions

I'm trying to see default argument promotion in functions. Specifically I want to test section 6.5.2.2 Function calls (described here).
I want to have a prototype-less function call to see default argument promotion to integer but I get "Function does not take 1 arguments" error. This is what I'm trying to do:
#include<iostream>
using namespace std;
//void Func(char val);
//void Func(int val);
void Func(); // No prototype
int main(int argc, char** argv)
{
char charVal = 'a';
cout << "Func(charVal) - "; Func(charVal);
return 0;
}
void Func(char val)
{
cout << "Char arg. Result: " << val << endl;
}
void Func(int val)
{
cout << "Int arg. Result: " << val << endl;
}
I expected to see Func(int) being called due to argument promotion.
Is this removed from the standard already?
Cheers.
P.S- I just saw that this kind of prototype-less declarations are part of C standard, NOT C++. Any particular reason why C++ doesn't support it?
All functions (and named entities in general) need to be declared before use. You've only declared the overload with no parameters (which is what an empty parameter list means in C++) when you try to call it with an argument in main.
You have the correct declarations at the start of the file, but for some reason the one you need is commented out. Uncomment them and it's fine.
I just saw that this kind of prototype-less declarations are part of C standard, NOT C++. Any particular reason why C++ doesn't support it?
Because C++ supports overloading. Overload resolution happens at compile time, where the function is called, and candidates can only be considered if the compiler knows they exist - that is, if they've been fully declared so that the compiler can match their signatures against the argument types of the function call.
In C, the compiler knows which function you mean, whether or not it knows the parameter types, since it's the only one with that name. Such declarations are merely dangerous, removing type-checking from the argument types and opening the door to all manner of bugs.
C++ has never supported prototype-less function declarations. The empty argument list in C++ means no arguments, not a lack of prototype.
The reason is that C++ has type-safe linking, and that just doesn't work if you don't have a prototype. And C++ has type-safe linking because that's just a good idea and reduces bugs. (You can read Design&Evolution of C++ for more details.)
Argument promotions in C++ exist only in calls to true variadic functions, i.e. those declared with a ... in the argument list.

Unexpected success of C Code

I am testing the following code in Code::Blocks v 12.11:
#include <stdio.h>
int main()
{
display();
return 0;
}
void display()
{
printf("\nHi");
}
It compiles successfully and runs well.I am unable to understand why?
My queries are as follows:
A function or variable needs to be at least declared before getting used in C/C++. Here,there is no declaration before we called the function display().
By default,all functions have return type as int.So,I am expecting a compilation error here but it went through successfully.The compiler would have assumed display() to be int display() and then we defined it as void display().
In C++, functions must be declared or defined before being use; that code cannot be C++.
In C89 or pre-standard C, if the compiler encounters an identifier followed by an open parenthesis, it is a function call, and if there is no declaration or definition in effect, then the return type is implicitly int and the number and types of the arguments is unspecified. (Thus, in the example, display() is a function returning an int and taking an indefinite — but not variable — number of arguments.)
In C99 or C11, in any strict compliance mode, you must have a declaration or definition of the function in scope before calling. It still doesn't have to be a prototype (the inferred declaration int display(); is not a prototype, and the definition is also not a prototype — it would need to be int display(void) to provide a prototype!).
Because of the inferred type for display() and the contradictory definition, you should get a compilation error, I believe. It would be at best a sloppy compiler that allowed it through, even in C89 mode. Indeed, I think even a pre-standard compiler should complain about the difference between the assumed and actual return types, but of course there was no standard so you couldn't complain (and, in any case, that standard is 24 years old now — compilers that only support that are verging on the archaic).
Which compiler (and version) are you using on which platform?
GCC 4.8.2 on Mac OS X 10.9, even with things set as permissive as possible, says:
dec.c:9:6: warning: conflicting types for ‘display’ [enabled by default]
void display()
^
dec.c:5:5: note: previous implicit declaration of ‘display’ was here
display();
^
Your code works perfectly well as a .c file and shows error when it is executed as a .cpp file
I hope this post explains why.
Why are function declaration mandatory in C++ and not in C?

Ambiguous call to overloaded static function

I'm confused by this situation and googling didn't give me the answer. Basically I have the following simple code that doesn't compile:
#include <iostream>
class A
{
public:
int a(int c = 0) { return 1; }
static int a() { return 2; }
};
int main()
{
std::cout << A::a() << std::endl;
return 0;
}
In compiling this, GCC 4.2 says the call to A::a() in main() is ambiguous with both versions of a() valid candidates. Apple's LLVM compiler 3.0 compiles with no error.
Why is gcc confused about which function I want to call? I thought it was obvious that by qualifying a() with A:: I'm asking for the static version of the function. Naturally this code still doesn't compile if I remove the static function a(), because A::a() is not valid syntax for calling the non-static a().
Thanks for any comment!
The reason for this is because C++ specifies that this is ambiguous. Overload resolution specifies that for A::a, since this is not in scope, the argument list in that call is augmented by a contrived A object argument, instead of *this. Overload resolution does not exclude non-static member functions, but instead
If the argument list is augmented by a contrived object and overload resolution selects one of the non-static member functions of T, the call is ill-formed.
This has recently been subject of extensive discussion both in the committee in context of core issue 1005. See core issue 364 which considered changing this rule but didn't do so.
The reason is name resolution happens before anything else the compiler does, like figuring out which overloaded function to use.
Qualifying the function with A:: simply tells the compiler to "look inside of A to find the name a". It doesn't actually help resolve which function you are referring to.
EDIT
And so when you type A::a(), first the compiler thinks "look in A for a member function or member who can use operator()".
Then the compiler thinks, "Ok, two possibilities here, which one is being referred to? a() or a(int c = 0) with a default c=0. Not sure.
If you removed the static keyword and called the functions like obj.a(), there would still be an ambiguity.
WRT LLVM's parser
I would say that it does some extra work for you, which is not required by the standard, which would be to assume A::a() is static.