我尝试做一个花哨的宏来获得一些调试信息:你目前的范围名称!这可以通过例如一个断言。我试图让它递归:
// Global namespace
struct ScopeDef{ static const char* GetName() {return "";} };
typedef ScopeDef ScopeDefParent;
// Macro to place into your namespace/scope
#define NG_SCOPEDEF(scopename) \
struct ScopeDef { \
static const char* GetName() {return scopename;} \
typedef ScopeDefParent Parent; \
}; \
typedef ScopeDef ScopeDefParent;
使用它像:
// Recursive template for testing
template< class T > void PrintImpl() {
PrintImpl< T::Parent >();
printf("::%s", T::GetName() );
}
template<> void PrintImpl< ::ScopeDef >() {}
template< class T > void PrintS() { PrintImpl<T>(); printf("\n");}
// Lets try it:
namespace First {
NG_SCOPEDEF( "First" );
namespace Second {
NG_SCOPEDEF( "Second" );
static void AFun() {
// This prints "::First::Second"
PrintS<ScopeDef>();
}
}
struct Third {
NG_SCOPEDEF( "Third" );
static void BFun() {
// This is endless recursion
PrintS<ScopeDef>();
}
};
}
它在类范围内不起作用,因为定义的顺序无关紧要。
这不是一个好的解决方案。那么有没有办法以某种方式访问父作用域?在常规代码中,我只会限定(“:: First :: ScopeDef”),但这对宏来说没什么。
答案 0 :(得分:1)
你可以在C ++中做这样的事情,你可以在每次打开一个范围时放入宏,让析构函数在范围退出时进行清理。此示例将打印出整个范围到stderr,此代码的输出如下。
main
main::First
main::First::Second
main::First::Second::DummyClass::DummyFunction
main::First
main
以下是代码:
#include <stdio.h>
class NG_SCOPE_CLASS;
NG_SCOPE_CLASS* NG_SCOPE_END = 0;
class NG_SCOPE_CLASS
{
public:
NG_SCOPE_CLASS(const char* scope)
{
_scope = scope;
_prev = NG_SCOPE_END;
NG_SCOPE_END = this;
}
~ NG_SCOPE_CLASS()
{
NG_SCOPE_END = _prev;
}
void PrintScope()
{
if(_prev)
{
_prev->PrintScope();
fprintf(stderr, "::");
}
fprintf(stderr, "%s", _scope);
}
private:
NG_SCOPE_CLASS* _prev;
const char* _scope;
};
#define NG_SCOPE_PRINT { if(NG_SCOPE_END) { NG_SCOPE_END->PrintScope(); fprintf(stderr, "\n"); } }
#define NG_SCOPE(X) NG_SCOPE_CLASS _NG_SCOPE_CLASS(X)
// THAT'S IT FOR THE DEFINITIONS ABOVE, BELOW IS JUST SOME SAMPLE CODE.
class DummyClass
{
public:
void DummyFunction()
{
NG_SCOPE("DummyClass::DummyFunction");
NG_SCOPE_PRINT;
}
};
int main(int argc, const char* argv[])
{
NG_SCOPE("main");
NG_SCOPE_PRINT;
{
NG_SCOPE("First");
NG_SCOPE_PRINT;
{
NG_SCOPE("Second");
NG_SCOPE_PRINT;
DummyClass theDummyInstance;
theDummyInstance.DummyFunction();
}
NG_SCOPE_PRINT;
}
NG_SCOPE_PRINT;
}
答案 1 :(得分:0)
为了完整性,我们的工作解决方案:
#if defined(_MSC_VER)
// GCC solution below. Note MSVC gives warning about unused typedefs but can be suppressed.
#define NG_SCOPEDEF(scopename) \
struct ScopeDefTag { static const char* Name(){return (scopename);}; }; \
typedef ::Scopes::Impl< ScopeDefTag, ScopeDef > ScopeDefHelper; \
struct ScopeDef : ScopeDefHelper {}
#else
// GCC seems to not look ahead.
#define NG_SCOPEDEF(scopename) \
struct ScopeDefTag { static const char* Name(){return (scopename);}; struct SDH : ::Scopes::Impl< ScopeDefTag, ScopeDef >{}; }; \
struct ScopeDef : ScopeDefTag::SDH {}
#endif
namespace Scopes {
struct Chain {
const char* const m_Lit;
const Chain* const m_Prev;
Chain(const char* lit, const Chain* prev) :m_Lit(lit), m_Prev(prev) {}
};
template< bool DMY = true >
struct RootScopeDef
{
static const Chain chain;
static const Chain* Get() { return &chain; }
};
// Being template just to have this in header:
template< bool DMY > const Chain RootScopeDef<DMY>::chain = Chain( "", 0 );
template< class TAG, class PARENT >
struct Impl {
static const Chain chain;
static const Chain* Get() { return &chain; }
typedef PARENT Parent;
};
template< class TAG, class PARENT >
const Chain Impl<TAG, PARENT>::chain = Chain( TAG::Name(), &PARENT::chain );
} // namespace
// Global namespace
typedef Scopes::RootScopeDef<> ScopeDef;
它基于编译器的漏洞而且不符合标准! MSVS认为用作模板参数的ScopeDef不是下一个,因为它取决于那个非常类型的参数,所以它解析为父类,后面将被遮蔽。当宏放在模板中时,这也有效,因为MSVS懒惰地实例化它们。相反,海湾合作委员会似乎没有向前看并将SDH的基础解析为正确的基础。 MSVS会在这里产生一个无限循环的m_Prev引用。
底线:这为您打印出用于调试目的的命名空间和类提供了一种很好的方法,但也可用作例如类型的类型。模板的专业化!