当然,除了全球范围之外。
我有一个带有宏的自定义断言类,用于缓存对__FILE__
的引用:
#define DEFINE_THIS_FILE \
static const char THIS_FILE__[] = __FILE__
对于源代码,使用宏没什么大不了的,因为每个源都有自己的范围。但是,模板化的类不能使用源代码,所以我不得不在TemplateClass.h给出的声明/定义中进行所有的ASSERT()调用。
如果我在类定义之外使用我的宏,例如Singleton
DEFINE_THIS_FILE;
namespace NE
{
template<typename T>
class Singleton
{
...
}
}
然后宏会在#includes Singleton
的任何代码的相同范围内结束,并且编译器会为THIS_FILE__
抛出重新定义错误。 (当然,只有当其他代码 使用DEFINE_THIS_FILE
宏时才会发生这种情况。)
如果我将宏放在声明中,编译器就不会抱怨,但链接器将无法为模板化类的任何给定实例找到THIS_FILE__,例如Singleton
:
namespace NE
{
template<typename T>
class Singleton
{
constexpr DEFINE_THIS_FILE; // constexpr modifier required in this case
...
}
}
我假设我得到链接器错误,
Undefined symbols for architecture x86_64:
"NE::Singleton<NE::NonTemplateType>::THIS_FILE__"
是由与第一次定义THIS_FILE__
的范围不同的模板实例引起的,Singleton.h
Singleton
的所有实例共享一个范围(全局是不可接受的),以便所有实例都可以使用这个静态const宏? EDIT1
进一步测试证实:在包含ASSERT()的每个模板化方法中使用宏DEFINE_THIS_FILE
将编译并正确运行....
在这种情况下,实例不共享范围,但为每个方法定义了static const char THIS_FILE__
。这是有效的,但我怀疑它使用了比std :: assert更多或更多的ROM(其隐含的__FILE__
分配)。
我会满足于此,直到OT的答案出现:)
EDIT2
傻我。我不如使用上面编辑中列出的变通方法,而是创建另一个宏,UNCACHED_ASSERT(argsToCheck)直接使用__FILE__
而不是const静态表示。
但是,每种方法的多个ASSERT仍然可以从缓存中受益。
但仍然需要OT的答案。
答案 0 :(得分:1)
您可以将声明放在未命名的命名空间
中#define DEFINE_THIS_FILE namespace { static const char THIS_FILE__[] = __FILE__; }