Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward declaring a function in a namespace inside another function in that namespace

I have two source files, a.cpp and b.cpp. In a.cpp, I have a function, foo:

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

In b.cpp, I have another function in namespace ns in which I'd like to prototype and call foo:

namespace ns
{

void bar()
{
    void foo();
    foo();       
}

}

While the above is syntactically valid, it leads the compiler to think that foo is in the global namespace (or at least that's what I've deduced from the linker errors I get when I do this). My first two ideas to fix that were void ns::foo(); and namespace ns { void foo(); }, but neither is valid. Is it possible to correctly prototype this function inside bar?

Note that I know I could simply move this to the file scope or a header file, there have been many questions asked about this, but I want to specifically prototype it inside another function. My compiler is MSVC 14.0 with the latest update.

EDIT: Based on some tests I've done and our discussion in the comments, I believe this is an MSVC bug. Compare:

namespace ns
{

void bar()
{
    void foo();   // link error, MSVC assumes global namespace
    foo();
}

void foo() { }

} // namespace ns

This fails, as stated previously. However, moving the prototype out of the function makes MSVC correctly place the prototyped function in the enclosing namespace:

namespace ns
{

void foo();   // all fine
void bar()
{
    foo();
}

void foo() { }

} // namespace ns
like image 490
user4520 Avatar asked Jan 01 '16 20:01

user4520


1 Answers

The standard is clear about this point:

3.3.2/11: (..) Function declarations at block scope and variable declarations with the extern specifier at block scope refer to declarations that are members of an enclosing namespace (...)

Consequently:

void bar()
{
    void foo();   // should refer to ns::foo() according to 3.3.2/11
    foo();
}

and the linking should refer to the separately compiled function which has the same signature:

1.3.17 signature: <function> name, parameter type list , and enclosing namespace (if any) [Note: Signatures are used as a basis for name mangling and linking.—end note ]

like image 65
Christophe Avatar answered Oct 01 '22 12:10

Christophe