Let's assume there are a number of variables defined in namespace library::symbols that are supposed to initialize on startup, like this:
namespace library {
class Symbol; // details not relevant here
namespace symbols {
inline const Symbol S1 = Symbol("S1");
inline const Symbol S2 = Symbol("S2");
}
}
Now, I need to add more of those from other places, referencing back into the symbols namespace (pseudo code):
namespace app {
namespace ::library::symbols {
inline const Symbol S3 = Symbol("S3");
inline const Symbol S4 = Symbol("S4");
}
}
The rationale behind this is to have an extensible set of global constants that can be compared, parsed and printed at runtime (example names S1...S4 are arbitrary here).
The example doesn't compile. I tried a bunch of ideas, but can't seem to find any solution yet. What am I missing? Is there a way to reopen and extend the library::symbols namespace? Is there an alternative to achieve this, e.g. via template specialization?
EDIT:
Reframed the question and second code snippet to be more precise. The issue I have is how to extend a namespace outside the current namespace. In the example, I would need to extend symbols while inside namespace app.
So the question is if there's a way to alias back into a higher-level namespace without this causing the declaration of a new one.
Is there a way to reopen and extend the library::symbols namespace?
Yes, you said it. Just reopen the library::symbols namespace and put more data in it. For example:
namespace library
{
class Symbol;
namespace symbols
{
inline const Symbol S1 = Symbol("S1");
inline const Symbol S2 = Symbol("S2");
}
}
// Maybe in another file
namespace library
{
class Symbol;
namespace symbols
{
inline const Symbol S3 = Symbol("S1");
inline const Symbol S4 = Symbol("S2");
}
}
namespace app
{
using namespace library;
Symbol dummy()
{
// Here use a namespace variable
return symbols::S3;
}
}
You just have to remember to include the correct header if you reopen the namespace in another file.
Just do what you did in the declaration of first set of variables:
namespace library {
namespace symbols {
inline const Symbol S3 = Symbol("S3");
inline const Symbol S4 = Symbol("S4");
}
}
Edit:
In the example, I would need to extend symbols while inside namespace app.
This isn't possible. The solution is to not try to do that. Close the namespace app, then follow the example I gave above. You can re-open app afterwards if necessary.
Related
I know that this subject has already been discussed on this site, I tested the solutions but it doesn't work, I always have the same mistake. Please help me :')
Player.cpp
#include "Player.hpp"
namespace Player
{
const char *name = "Jason";
}
Card.cpp
#include "Player.hpp"
namespace Player
{
const char *name = "Jason";
}
Player.hpp
namespace Player
{
extern const char *name;
}
You can have at most one definition of each unique fully-qualified symbol in your program. The linker error you are receiving is occurring because you provide a definition for the symbol Player::name in both Player.cpp and Card.cpp.
You are free to reuse variable names; but the symbol must still be unique to avoid these issues. For your particular problem, this may be solved through one of the following:
Defining the symbol in a different namespace
For example, you could change Card.cpp to be:
// Symbol is Card::name -- which is different from Player::card
namespace Card {
const char* name = ...;
} // namespace
Defining the symbol as a static member of a struct/class
This could be something like:
// Symbol is Player::Card::name -- which is different from Player::card
namespace Player {
struct Card {
static const char* name = ...;
};
}
Marking the symbol with internal linkage
This could be done using an unnamed namespace (C++11 and above), or static (older C++):
// Symbol is Player::<some unique name>::name
namespace Player {
namespace {
const char* name = ...;
}
// or 'static const char* name = ...;'
}
note: This method, unlike the others, cannot be used across different source files. The symbol is "internalized", which means it is unique to the one compilation unit (source file).
namespace noob questions
I have two files in the same binary.
// class1.cpp
namespace A {
const std::string k1 = "abc";
}
// class2.cpp
namespace A {
const std::string k1 = "bcd";
}
They are not declared in header file.
Won't they collide?
I tried to compile and it can compile.
I should put them to unnamed namespace but even if I don't, it still seems to be able to compile.
Why is that
Edit: Those two files are actually included to build the same binary.
It is because const implies internal linkage. You will get the expected error about duplicate symbols if you defined A::k1 as non const.
My function test is added to two different .cpp-files and the functions are private to their respective files as shown below
test1.cpp
#include <iostream>
using namespace std;
void test()
{
cout << "test" << endl;
}
test2.cpp
#include <iostream>
using namespace std;
void test()
{
cout << "test" << endl;
}
main.cpp
#include <iostream>
using namespace std;
int main()
{
return 0;
}
During linking I get the error multiple definition of test() - but how is that possible, considering that the two files have their own private scope!? I could understand it if I included the function prototype in each .cpp-files' corresponding header, but there is no such thing in this example.
You need the inline keyword for that:
inline void test()
{
cout << "test" << endl;
}
This allows you to have multiple definitions in separate source files without violating the one-definition rule. However, note that the function still has external linkage and they will all resolve to the same address. Also:
An inline function shall be defined in every translation unit in which
it is odr-used and shall have exactly the same definition in every
case
If you want separate functions with different addresses (internal linkage), use the static keyword instead.
Both test functions are in the same global namespace of the program. In order to avoid error you may:
1) wrap any or both functions in namespace:
namespace A
{
void test()
{
...
}
}
2) use static keyword
3) just rename one of them
Add static in each test function.
#include <iostream>
using namespace std;
static
void test()
{
cout << "test" << endl;
}
To elaborate on above answers:
In C++, function declarations can be repeated as many times as you want. A function definition however (i.e. the function body), can occur only once.
When creating your binary, the compiler compiles each file to a obj file so in your example you end up with test1.obj, test2.obj and main.obj. After all files compiled successfully, the linker links them together to create your executable. This is where multiple definitions for the same function are found and why linking fails.
Depending on what you want, you can do the following to resolve this:
If you want multiple different functions with the same name, then you have to disambiguate them. C++ wouldn't be C++ if you only had one way to do this:
The old c way: use the static keyword
Use an anonymous namespace
Use a namespace
If you want only one function:
Separate the definition from the declaration, i.e. put the declaration in a header file and move the definition to a source file.
Define the function as inline in a header
Is there any difference between wrapping both header and cpp file contents in a namespace or wrapping just the header contents and then doing using namespace in the cpp file?
By difference I mean any sort performance penalty or slightly different semantics that can cause problems or anything I need to be aware of.
Example:
// header
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
// cpp
namespace X
{
void Foo::TheFunc()
{
return;
}
}
VS
// header
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
// cpp
using namespace X;
{
void Foo::TheFunc()
{
return;
}
}
If there is no difference what is the preferred form and why?
The difference in "namespace X" to "using namespace X" is in the first one any new declarations will be under the name space while in the second one it won't.
In your example there are no new declaration - so no difference hence no preferred way.
Namespace is just a way to mangle function signature so that they will not conflict. Some prefer the first way and other prefer the second version. Both versions do not have any effect on compile time performance. Note that namespaces are just a compile time entity.
The only problem that arises with using namespace is when we have same nested namespace names (i.e) X::X::Foo. Doing that creates more confusion with or without using keyword.
There's no performance penalties, since the resulting could would be the same, but putting your Foo into namespace implicitly introduces ambiguity in case you have Foos in different namespaces. You can get your code fubar, indeed. I'd recommend avoiding using using for this purpose.
And you have a stray { after using namespace ;-)
If you're attempting to use variables from one to the other, then I'd recommend externalizing them, then initializing them in the source file like so:
// [.hh]
namespace example
{
extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
int a, b, c;
}
// Then in the function below, you can init them as what you want:
void reference
{
example::a = 0;
}
If the second one compiles as well, there should be no differences. Namespaces are processed in compile-time and should not affect the runtime actions.
But for design issues, second is horrible. Even if it compiles (not sure), it makes no sense at all.
The Foo::TheFunc() is not in the correct namespacein the VS-case. Use 'void X::Foo::TheFunc() {}' to implement the function in the correct namespace (X).
In case if you do wrap only the .h content you have to write using namespace ... in cpp file otherwise you every time working on the valid namespace. Normally you wrap both .cpp and .h files otherwise you are in risk to use objects from another namespace which may generate a lot of problems.
I think right thing to do here is to use namespace for scoping.
namespace catagory
{
enum status
{
none,
active,
paused
}
};
void func()
{
catagory::status status;
status = category::active;
}
Or you can do the following:
// asdf.h
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
Then
// asdf.cpp
#include "asdf.h"
void X::Foo::TheFunc()
{
return;
}
what is the use of using declaration type of namespacing over using directive type of namespacing??when to use each one of them?
The declaration type of namespace directive introduces selected named symbols into your code scope (and leaves other symbols from the same namespace inaccessible without the namespace qualifier).
The using type of namespace directive introduces all symbols from the namespace into your code scope - which means you don't necessarily know exactly which symbols were introduced (there could have been undocumented symbols, or symbols left over from previous versions of the library, or ...).
For control, use the declaration type of namespace directive.
For convenience (with risk), use the using type of namespace directive.
Besides the using declaration allowing access to a symbol rather than a namespace, the using declaration also brings the symbol to the scope of the declaration. The using directive only affects lookup.
Jonathan already resumed the differences between using namespace foo; and using foo::Bar; but I think his answer is unfortunately incomplete.
First: using namespace should never appear in a header file. By doing so you might render it impossible to use in combination with other header files because of a symbol clash...
Second: in general, you should try to limit the scope of the symbols as much as possible, you probably already do it while writing code:
for (size_t i = 0; i < 5; ++i)
{
std::string myString = myVec.at(i);
if (myString == "Foo") { std::cout << "Found"; break; }
}
Here it would be useless (and polluting) to have myString declared outside the for loop. In fact, that very advice can be found in a number of books:
From Scott Meyers' Effective C++, Item 26: Postpone variable definitions as long as possible.
From Herb Sutter and Andrei Alexandrescu's C++ Coding Standard, Item 18: Declare variables as locally as possible
There is no reason not to do the same with using declarations.
Third: consider alternatives to using: namespace aliasing and typedef.
// foo.h
class Foo
{
public:
std::vector<std::string> getSynonyms(const std::string& s) const;
private:
typedef std::map< std::string, std::vector<std::string> > synonyms_type;
synonyms_type mSynonyms;
};
// foo.cpp (never in header, at general scope)
namespace fu = boost::fusion;
std::vector<std::string> Foo::getSynonyms(const std::string& s) const
{
synonyms_type::const_iterator it =
std::find(mSynonyms.begin(), mSynonyms.end(), s);
std::vector<std::string> result;
if (it != mSynonyms.end()) { result = it->second; }
return result;
}
What are the advantages ?
namespace aliasing > reduce typing almost as much without injecting the types right in the current scope so without risk
typedef > reduce typing more than using and allow easy change of underlying type too.