Why does C++ code missing a formal argument name in a function definition compile without warnings?

Viewed 26639

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 Answers

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.

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