【发布时间】:2013-01-12 08:13:16
【问题描述】:
当然,除了全局范围。
我有一个带有宏的自定义断言类来缓存对__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
OT:有没有办法让我的模板类型 Singleton 的所有实例共享一个范围(全局是不可接受的),以便所有实例都可以使用这个静态 const 宏?
编辑1
进一步的测试证实:在包含 ASSERT() 的每个模板化方法中使用宏 DEFINE_THIS_FILE 将正确编译和运行....
在这种情况下,实例不共享范围,但为每个方法定义了 static const char THIS_FILE__。这可行,但我怀疑它使用的 ROM 与 std::assert 一样多或更多(其隐含分配 __FILE__)。
我会解决这个问题,直到对 OT 的回答出现:)
编辑2
傻我。除了使用上面编辑中列出的解决方法,我还不如创建另一个宏 UNCACHED_ASSERT(argsToCheck) 直接使用 __FILE__ 而不是 const 静态表示。
不过,每个方法的多个 ASSERTions 仍然可以从缓存中受益。
不过,仍然需要对 OT 的回答。
【问题讨论】:
-
OT:我真的很好奇。是否有某些原因您不只是将
__FILE__用于您使用THIS_FILE__的任何邪恶目的?毕竟,它是由标准定义的,用于命名您在其中使用它的任何源文件。 -
正如您自己所说,以这种方式使用时,它将反映包含的 cpp 文件的名称。它是否适用于您期望的标题?
-
任何有价值的编译器都会为每个文件发出一个字符串的副本。我知道我的。检查你的做法,不要相信那些在更古老的文章中找到智慧的古老文章(1993 年,这甚至不好笑)。
-
两种方法: 1. 用
-S标志编译,看汇编输出; 2.strings yourfile.o | fgrep yourfile.C. -
您是否尝试将宏放在未命名的命名空间中?
#define DEFINE_THIS_FILE namespace { static const char THIS_FILE__[] = __FILE__; }
标签: c++ templates macros scope