//file.h
namespace first
{
namespace second
{
void foo();
}
}
//file.c
using namespace first::second;
void foo()
{
...
}
//main.c
using namespace first::second;
int main()
{
foo();
}
the code above doesn't work as the compiler didn't recognize the foo(). where is my mistake?
try this:
This puts the implementation into the namespace
//file.c
namespace first
{
namespace second
{
void foo()
{
...
}
}
}
This tells main explicitly where to find foo:
//main.c
int main()
{
::first::second::foo();
}
I'm going to guess that you got an unresolved linking error when you tried to call foo from main in the example you posted. There are couple issues at play here starting from the top:
file.h declares a foo existing in namespace first::second.
file.c brings namespace first::second into filescope lookup but it does not affect function definitions. Thus the implementation of void foo() {} is actually a function defined in global scope -- not in first::second as you might expect.
main.c brings namespace first::second into its filescope. The compiler will consider first::second as well as global scope :: when you call foo in main. The compiler chooses first::second::foo since file.h doesn't declare the global foo().
you get a linking error for unresolved symbol because first::second::foo was never implemented.
In addition to Jay's suggestion, the other fix you can do is to fully qualify foo's definition similar to member functions:
// file.c
#include "file.h"
void first::second::foo()
{
// ...
}
Related
Does the "using" keyword have different effects in the context of defining member and non-member functions? The example code below suggests to me that it might.
main.cpp
#include "baz.h"
int main()
{
foo::bar x;
x.baz();
foo::foo_non_member();
}
baz.h
namespace foo
{
class bar
{
public:
bar() = default;
void baz();
};
void foo_non_member();
};
baz.cpp
#include "baz.h"
#include<iostream>
using namespace foo;
void bar::baz()
{
std::cout << "baz\n";
}
namespace foo
{
void foo_non_member()
{
std::cout << "non-member\n";
}
}
The above code compiles and runs.
$> g++ main.cpp baz.cpp; ./a.out
baz
non-member
If I remove the using namespace foo; from baz.cpp, I get a compiler error.
$> g++ main.cpp baz.cpp
baz.cpp:5:6: error: ‘bar’ has not been declared
void bar::baz()
If I put that using statement back in and move the definition of foo_non_member() outside of the foo namespace, I get a linker error.
$> g++ main.cpp baz.cpp
/tmp/ccHeSwsZ.o: In function `main':
main.cpp:(.text+0x24): undefined reference to `foo::foo_non_member()'
collect2: error: ld returned 1 exit status
Why does the using keyword appear not to have the same effect here for bar::baz() and foo_non_member()?
For this part:
using namespace foo;
void bar::baz()
{
std::cout << "baz\n";
}
The using namespace foo; is used for the lookup of the bar:: part, and due to that the compiler is able to tie the definition of void bar::baz() to the declaration in the namespace foo.
And if you remove using namespace foo; it is not able to find bar.
If I put that using statement back in and move the definition of foo_non_member() outside of the foo namespace, I get a linker error.
void foo_non_member()
{
std::cout << "non-member\n";
}
Here foo_non_member not have any relation to bar:: or anything else (according to the specs) that would allow the compiler to figure out that this definition is related to the declaration in the namespace foo.
The standard committee for sure could have added some rules to the specification to allow the compiler to get the foo_non_member definition and the declaration together if the using namespace foo; is present but they decided to don't do so.
The reason for that is likely because you then would have the ambiguity about whether you want to define a new void foo_non_member() outside of the namespace foo or if you want to have a definition for void foo_non_member() of foo.
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?
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.
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.
I'm doing online programming tests like leetcode, which requires only one .cpp file, so I have to place everything into one .cpp file.
And I used to write main() function ahead of any other functions, but that way I have to forward declare every function I use, which is very annoying. So I think of something like the snippet below:
namespace function;//oop,there is no such forward declaration
int main()
{
using namespace function;//compiler could not find this actually;
f1();
...
}
namespace function
{
f1(){...};
f2(){...};
...
}
But the compiler complains, since there is no forward declaration of namespaces (unlike functions), which makes the namespace invisible to the compiler.
Is there any way to forward declare a namespace? Just like
void f1();
int main()
{
f1();//ok,because there is a forward declaration
}
void f1()
{ ...}
The nearest thing to forward-declaring a namespace is to rely on the fact that they can be split up (unlike a class declaration), even into different translation units! Hence you can write
namespace funcion // [sic]
{
}
before main. Note well the braces.
If not having to forward declare functions is the most important goal, you can abuse the fact that a class also defines a namespace scope where you don't have to forward declare member functions.
Something like this:
struct program
{
int main()
{
f1();
f2();
return 0;
}
void f1(){}
void f2(){}
};
// The real main still needed here
int main()
{ return program{}.main(); }
Technically this works, but still not really recommended.
This won't solve your problem.
You can declare the namespace earlier like this:
namespace function {};
int main()
{
using namespace function;
f1();
}
namespace function
{
void f1() {}
}
but f1 is still not declared in main.
How about extracting the function declarations to a header file and including it?
somefile.h
#pragma once
namespace function {
void f1();
};
somefile.cpp
#include "somefile.h"
int main()
{
using namespace function;//compiler could not find this actually;
f1();
}
namespace function
{
void f1() {}
}
so I have to place everything into one .cpp file
Then just forget the #include and do one of the following:
a. put the declaration namespace function { void f1(); } above int main() and the definition (function body) below int main()
b. put the int main() last, so that you don't require additional declarations
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
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 ]
When defining a function signature in an anonymous namespace within a .hpp, is it valid to place the implementation of that function within the .cpp? When I do so I get an undefined reference error.
Example:
//hpp
#ifndef __BAR_HPP_
#define __BAR_HPP_
namespace foo
{
namespace
{
struct Bar
{
void func();
};
}
}
#endif
//cpp
using foo;
void Bar::func()
{
//...
}
Think of this:
namespace foo
{
struct Bar
{
void func();
};
}
void Bar::func() { /*impl...*/ }
Your code doesn't work for the same reason this code doesn't -- the definition is being provided in the wrong scope. What's needed is:
void foo::Bar::func() { /*impl...*/ }
But what do you put in place of foo:: to refer to the name of an anonymous namespace? It doesn't have one.
Bottom line: it's not possible to declare something inside of an anonymous namespace then define it elsewhere, as no mechanism exists for specifying the proper scope.