6

Single File Example

Here is a simple program using namespaces.

#include <iostream>

namespace foo {
    void hello();
}

void foo::hello() {
    std::cout << "hello\n";
}

void foo::hello(); // Why is this syntax allowed? When is it useful?

int main() {
    foo::hello();
}

This program compiles fine and produces the expected output.

$ ./a.out
hello

I want to know when is the void foo::hello(); declaration useful? In this program, clearly this declaration is redundant. But since this syntax exists, this must be useful in some other scenario?

Two-File Example

Here is an example that shows that the void foo::hello(); declaration standing alone is useless.

// foo.cpp
#include <iostream>

namespace foo {
    void hello();
}

void foo::hello() {
    std::cout << "foo::hello\n";
}
// main.cpp
void foo::hello(); // This does not work!

int main()
{
    foo::hello();
}

Trying to compile the above two files leads to the following errors:

$ clang++ foo.cpp main.cpp
main.cpp:1:6: error: use of undeclared identifier 'foo'
void foo::hello();
     ^
main.cpp:5:5: error: use of undeclared identifier 'foo'
    foo::hello();
    ^
2 errors generated.

The only way to fix main.cpp in the above example seems to be include the namespace declaration:

// main.cpp - fixed
namespace foo {
    void hello();
}

void foo::hello(); // But now this is redundant again!

int main()
{
    foo::hello();
}

So after we get this code to compile properly, the void foo::hello(); declaration seems redundant again. Is there any scenario where such a declaration would be playing a useful role?

Lone Learner
  • 18,088
  • 20
  • 102
  • 200
  • 1
    for instance when there is a function with the same name in another namespace... which could happen in a large project and or when using APIs – JHBonarius May 17 '18 at 11:36
  • 2
    @JHBonarius I can always specify which `hello()` I want to call by specifying the namespace, e.g. `foo::hello();` or `bar::hello();` while writing the actual call. What purpose does the `void foo::hello();` declaration serve? I don't see it playing any role in selecting which namespace's `hello()` I want because I specify that myself while calling `hello()`. – Lone Learner May 17 '18 at 11:39
  • 1
    Oh, wait: probably your question is about the **extra** declaration. I think it's the function prototype: then it's redundant. – JHBonarius May 17 '18 at 11:39
  • @JHBonarius The function prototype is already present here: `namespace foo { void hello(); }`. Of course `void foo::hello();` could be a prototype too but my question is why this second syntax is allowed and when would it be useful? – Lone Learner May 17 '18 at 11:41
  • AFAIK, it is just a shorthand if You have only one function in namespace or something. – bartop May 17 '18 at 11:42
  • @bartop It's a shorthand notation for what? I don't see what it has got to do with the namespace having only one function or more than one function. Why do you think I can't use this notation when there are more than two functions in a namespace? – Lone Learner May 17 '18 at 11:43
  • Imho its just an extra prototype. This even compiles: http://cpp.sh/8uuuy – JHBonarius May 17 '18 at 11:45
  • @JHBonarius Sure, it's just an extra prototype. My question is: Why is this syntax allowed and is there a situation when this syntax is actually useful? – Lone Learner May 17 '18 at 11:48
  • 1
    @LoneLearner Instead of opening namespace writing declaration and closing namespace You can write "myns::myfoo". It just saves few keystrokes – bartop May 17 '18 at 11:48
  • 1
    @bartop I am not sure what you mean. It is necessary to have a declaration that opens a namespace with `namespace {` and closes it with `}`, otherwise it does not seem to work: https://ideone.com/xVqfsg Can you post actual working code for what you mean? – Lone Learner May 17 '18 at 11:54

2 Answers2

3

In most cases in C++, for anything that can be either declared without defining it or can be completely defined, a declaration or a definition of that thing can appear in all the same contexts. So this is probably just a way of keeping the pattern consistent.

The C++ Standard does not go out of its way to forbid things that are a logical consequence of its other rules but just not useful, as long as it's reasonably clear what will happen if someone does it anyway. If it did add these restrictions, that would put extra work on compiler writers for no real benefit.

aschepler
  • 70,891
  • 9
  • 107
  • 161
0

From [basic.def]/1

A declaration may introduce one or more names into a translation unit or redeclare names introduced by previous declarations. If so, the declaration specifies the interpretation and attributes of these names.

Which allows code like this

#include <iostream>

void foo();
void foo();
void foo();
void foo();
void foo();

int main()
{
    foo();
}

void foo() { std::cout << "foo()"; }

To be valid. There is no harm in having multiple declarations of a function, as long as we have only one definition, it won't cause an issue.


Another example would be you have a global function you want to be a friend of multiple classes. You would include that function prototype in each class header so you can friend it and then you would include all of those class headers in your main source file. So

A.h
void foo();
struct A { friend void foo(); }

B.h
void foo();
struct B { friend void foo(); }

main.cpp
#include "A.h"
#include "B.h"

...

and that would be converted to

main.cpp
void foo();
struct A { friend void foo(); }

void foo();
struct B { friend void foo(); }

...

So we would want this to be legal.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402