views:

212

answers:

3

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?

+4  A: 

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.

Bill
It's the rational. (BTW, C need the parameter name)
AProgrammer
@AProgrammer: The question was about C++, not C.
Bill
@Bill: but it's still a valuable note (I find myself occasionally irritated by C's insistence on the parameter name)
Michael Burr
@Michael: Fair enough. I don't work with C all that much.
Bill
For the record, things like Q_UNUSED() usually expand to `__attribute__ ((unused))` on GCC.
greyfade
@greyfade: Looks like they don't do that anymore: http://qt.gitorious.org/qt/qt/blobs/master/src/corelib/global/qglobal.h, lines 1568-1574
Bill
@Bill: I was under the impression `Q_UNUSED` was to be used in parameter lists. Like so: http://sourcefrog.net/weblog/software/languages/C/unused.html
greyfade
@greyfade: Ah, I see the confusion. Q_UNUSED is meant to be used in the function body. I'll add a sample to my post.
Bill
+13  A: 

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.

Michael Burr
As an extra note, many compilers have a pragma to disable unused parameter warnings - more relevant when the parameter *has* a name of course - precisely because there are valid reasons why this may happen. Some prefer to leave the name in anyway, to indicate the intended use (according to the interface), even though it's not used in this case.
Steve314
I guess that makes sense -- I figured it was something along those lines, it just seemed (to me) like an unusual edge condition to explicitly allow, when (as noted below) C doesn't allow it. But your point about polymorphic calls is certainly valid, and makes sense for C++ to have considered it.
Andrew Coleson
+2  A: 

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?

AndreyT
I was looking for something along the lines of "why does the standard allow this", as the other answers have suggested. The answer "It compiles because it should" is..obvious to say the least.
Andrew Coleson
@Andrew Coleson: Well, for me the ability to omit the parameter name (whin it is not used) looks natural, an the rationale behind it - obvious. I have hard time understanding why someone would ask the "why" question. Actually, I would rather expect someone to ask why C *doesn't* allow this, not why C++ does. So, my answer above is supposed to mean the following: it is legal in C++ because C++ specification finally allowed it (as in "everybody was waiting for it, and in C++ it was finally made possible").
AndreyT
"Everybody wanted it in C and in C++ it was finally made possible" is a useful answer to "Why?", thank you.
Andrew Coleson