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.
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.
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 ]
//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()
{
// ...
}
I am having a lot of troubles with my C++ code but I can't understand why.
I am developing a static library libmylib.a that contains myclass.h and myclass.cpp.
The problem I am having is like this:
// myclass.h
class myClass{
public:
myclass();
myclass(a,b);
// some methods.
private:
int a ;
int b ;
};
In myclass.cpp I define the constructors methods etc etc and everything works fine:
I am able to use the library in my main.cpp code.
I then added a friend function:
// myclass.h
class myClass{
public:
myclass();
myclass(a,b);
friend void foo() ;
// some methods.
private:
int a ;
int b ;
};
I define the foo function in myclass.cpp like this
// myclass.cpp
void foo(){
cout << "In foo function " ;
}
The problem is that if I try to use foo() in main.cpp I get a compile error that states:
//main.cpp
#include "myclass.h" // foo() is declared here!
foo() ;
main.cpp:62:6: error: ‘foo’ was not declared in this scope
Now I really can't understand where the problem is.
I notice that after adding the friend function it seems that the linker doesn't use mylib anymore, but I can't understand why. Moreover it is strange, because if I comment foo() in main.cpp myclass and its methods can be used without problems.
What am I doing wrong? I spent two hours trying to figure out, but really can't understand!!!
Solution: following the advice in the answer:
// myclass.h
void foo() ; // the function has to be declared outside the class
class myClass{
public:
myclass();
myclass(a,b);
friend void foo() ; // but here you have to specify that
// is a friend of the class!
// some methods.
private:
int a ;
int b ;
};
This is not a linker error, it is a compiler error. The compiler is telling you that it does not know how to call function foo, because it lacks its definition or declaration.
Declaring a function as a friend is no substitute for a proper declaration. When you say foo is a friend, you do not also introduce foo into a scope. In a sense, friendship declaration is a private detail of your class invisible from the outside.
In order to use a function in C++ you need to declare it first. This is usually done through a header file corresponding to the implementation file, but you can do it simply like this:
void foo();
If foo is defined in the same file as main, you can move foo ahead of the main to fix the problem (seeing a function definition prior to first use is OK with the compiler).
Have you declared foo before using it:
#include "header_where_foo_is_declared.h"
int main()
{
foo();
}
or
void foo();
int main()
{
foo();
}
???
Is there a way in C++ to create an anonymous namespace, and only export a single function out of it?
I want something like:
namespace {
void Bar() {}
void Foo() { Bar(); }
}
Now, I want to somehow access to Foo() yet make sure there's no way to touch Bar()
Thanks!
If you want to export the function, you'll have to put it outside the anonymous namespace.
namespace {
void Bar() {};
};
void Foo() { Bar(); };
Since you want Foo() to have external linkage, you should declare it in a header file:
#ifndef FOO_H
#define FOO_H
void Foo();
#endif
Now everyone can see and call Foo()
But in Foo.cpp:
#include "Foo.h"
namespace {
void Bar(){ }
}
void Foo(){ Bar(); }
Now, as long as you control the source file Foo.cpp, no one can change access to Bar()
You could place them in different header files and make sure clients only get the header file that declares Foo(). However, you cannot implement Foo() inline with that solution.
why not
namespace {
void Bar() {};
};
void Foo() { Bar(); };
?
an anonymous namespace is accessible from the file you created it in
Define Bar as a global static function in the CPP file that contains the function body for Foo.
Edit: Its worth noting that this will only cause a link time error.
Edit2: And I ran a quick test and it seems you can't extern to an anonymous namespace.
Edit3:
Something like this would seem sensible (and lose the namespace)
static void Bar()
{
}
void Foo()
{
Bar();
}
You can now "extern void Foo();" but if you try the same with Bar then the linker will fail as Bar no longer has external linkage.