61

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?

Andrew Coleson
  • 10,100
  • 8
  • 32
  • 30

4 Answers4

78

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
  • 333,147
  • 50
  • 533
  • 760
  • 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. –  Feb 23 '10 at 16:28
  • 1
    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 Feb 24 '10 at 02:41
  • Another extra note on why there is no warning: The method signature does not depend on the name, right? only on the types in proper sequence. Thus the name can be left out altogether. Another reason for no warning becomes clear when thinking about why unnamed parameters are allowed at all: Mainly if the parameter must be present because the method is part of an interface requiring that the method has a prescribed signature and one has to avoid an unused variable warning if this variable is not used. Thus it would be counterproductive to emit a warning for unnamed parameter. – user2609605 Apr 26 '20 at 20:30
21

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
  • 14,257
  • 4
  • 43
  • 55
  • 1
    It's the rational. (BTW, C need the parameter name) – AProgrammer Feb 23 '10 at 16:10
  • 1
    @AProgrammer: The question was about C++, not C. – Bill Feb 23 '10 at 16:13
  • 2
    @Bill: but it's still a valuable note (I find myself occasionally irritated by C's insistence on the parameter name) – Michael Burr Feb 23 '10 at 16:23
  • For the record, things like Q_UNUSED() usually expand to `__attribute__ ((unused))` on GCC. – greyfade Feb 23 '10 at 17:53
  • @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 Feb 23 '10 at 18:16
  • @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 Feb 23 '10 at 18:22
  • @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 Feb 23 '10 at 19:03
7

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.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
0

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?

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 8
    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 Feb 24 '10 at 02:38
  • 1
    @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"). – AnT stands with Russia Feb 24 '10 at 13:05
  • 1
    "Everybody wanted it in C and in C++ it was finally made possible" is a useful answer to "Why?", thank you. – Andrew Coleson Feb 24 '10 at 15:34
  • 'There is no other answer' invalidates the other answers. But: this is the answer which is the least enlightening one. Of course, it compiles because the standard prescribes to to so. But the 'why' question means, why does the standard allow unnamed parameters explicitly. In fact this possibility was added belated in order so satisfy some need. What the need is, that is the question `why` which is perfectly legitimate. – user2609605 Apr 26 '20 at 20:35