I have some well-formed code looks like this:
NAMESPACE_BEGIN(Foo)
inline void test() {
string s = xxx;
}
NAMESPACE_END(Foo)
So, is there any portable tricks by using the NAMESPACE_BEGIN()
macro to obtain namespace name "Foo" in test()
?
I'm thinking of something like this, but it would surely cause symbol redefinition:
#define NAMESPACE_BEGIN(x) \
namespace x { \
inline const char *_curNamespace() { \
return #x; \
}
#define NAMESPACE_END(x) \
}
There's also a workaround looks like this, but that's not very convenient
#define NAMESPACE_NAME Foo
// using a header file so that we can use #ifdef guard
#include "MyNamespaceBegin.h"
...
#include "MyNamespaceEnd.h"
EDIT:
Why I need this:
I'm using much of macro to generate codes to achieve some dynamic reflection logic (yes, not static template reflection), it's all right within class scope by using static member function, but does not work for namespaces
Why not to manually declare the name getter once:
What I want is something like this:
// the global default version
const char *_curNamespace() {return "";}
namespace X {
// the local namespace version
const char *_curNamespace() {return "X";}
// some verbose reflection register code
...
registerSomething(_curNamespace());
...
}
Of course, all of the verbose register code should be generated by macro
And, app level user should not care about the _curNamespace()
,
so, I want to simplify the user's usage,
by using a custom NAMESPACE_BEGIN(xxx)
macro at any case
If you are still curious about what I'm doing, check this: https://github.com/ZFFramework/ZFFramework
I'm using lots of tricks to achieve fully dynamic reflection in pure C++, to achieve some of my fancy thoughts, for now, this project is just for fun, I have no idea whether it has practicability
EDIT2:
For now, I think the best workaround should be like this:
#define NAMESPACE_BEGIN(ns) \
namespace ns { \
extern const char *__curNS();
#define NAMESPACE_END(ns) \
}
#define NAMESPACE_REG(ns) \
const char *__curNS() {return #ns;}
NAMESPACE_BEGIN
NAMESPACE_REG
must be declared exactly once, in source file
NAMESPACE_REG
,
the strict rule should prevent user from forgetting the ugly workaroundNo, C does not have a namespace mechanism whereby you can provide “module-like data hiding”.
A file path, which uses syntax defined by the operating system, is considered a namespace. For example, C:\Program Files\Internet Explorer is the namespace that describes where Internet Explorer files on a Windows computer.
Inside a namespace, no two classes can have the same name.
C++ allows us to define our own namespaces via the namespace keyword. Namespaces that you create for your own declarations are called user-defined namespaces. Namespaces provided by C++ (such as the global namespace ) or by libraries (such as namespace std ) are not considered user-defined namespaces.
You are making much fuss over something that is trivial to implement.
First of all, use of NAMESPACE_BEGIN
and NAMESPACE_END
seems unnecessary to me. I don't see how that is more readable or useful than
namespace Foo
{
}
If getting the name of the namespace
is important/useful, add a trivial function.
namespace Foo
{
inline std::string get_name() { return "Foo"; }
}
Small sized real world applications need thousands of lines of code. Large sized real world applications need millions of lines of code. From that perspective, implementing a one line inline
function is a very minor task.
This solution employs a bit of preprocessor magic and has these features:
It does not support nested namespaces.
Example of usage:
#include "framework.hpp"
#define NAMESPACE_NAME Foo
#include NAMESPACE_BEGIN
// Here you have access to NAMESPACE_NAME (unquoted, i.e. Foo)
// and also to NAMESPACE_NAME_STRING (quoted, i.e. "Foo")
#include NAMESPACE_END
// NAMESPACE_NAME and NAMESPACE_NAME_STRING do not exist
// outside the block, so they cannot be misused
// Different namespaces in the same TU are supported
#define NAMESPACE_NAME Bar
#include NAMESPACE_BEGIN
inline std::string f()
{
return NAMESPACE_NAME_STRING;
}
#include NAMESPACE_END
// Repeating the same namespace is also supported
#define NAMESPACE_NAME Foo
#include NAMESPACE_BEGIN
inline std::string f()
{
return NAMESPACE_NAME_STRING;
}
#include NAMESPACE_END
The implementation follows:
framework.hpp
#pragma once
#define NAMESPACE_BEGIN "framework_namespace_begin.hpp"
#define NAMESPACE_END "framework_namespace_end.hpp"
framework_namespace_begin.hpp
#ifndef NAMESPACE_NAME
#error "NAMESPACE_NAME not defined"
#endif
#define NAMESPACE_IN_NAMESPACE 1
#define NAMESPACE_NAME_DO_STR(X) #X
#define NAMESPACE_NAME_STR(X) NAMESPACE_NAME_DO_STR(X)
#define NAMESPACE_NAME_STRING NAMESPACE_NAME_STR(NAMESPACE_NAME)
namespace NAMESPACE_NAME {
framework_namespace_end.hpp
#ifndef NAMESPACE_IN_NAMESPACE
#error "NAMESPACE_IN_NAMESPACE not defined"
#endif
}
#undef NAMESPACE_NAME
#undef NAMESPACE_NAME_STRING
#undef NAMESPACE_IN_NAMESPACE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With