【发布时间】:2013-12-26 07:43:23
【问题描述】:
假设您在应用程序中使用模板类,例如std::tuple (或 std::shared_ptr 或其他),并且您有这样的实例化:
typedef std::tuple<Book,Library> BookLibrary;
typedef std::tuple<Book,Chapter,Reader> BookChapterReader;
然后您在其他模板类中使用这些实例化,例如作为类成员的 std::map:
class X
{
...
private:
std::map<Library,BookChapterReader> m_data;
};
然后生成的 PDB 文件将包含如下描述(使用 Microsoft 调试工具的 DBH 实用程序查看):
std::_Tree<std::_Tmap_traits<Library,std::tr1::tuple<Book,Chapter,Reader,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>,std::less<Library>,std::allocator<std::pair<Library const ,std::tr1::tuple<Book,Chapter,Reader,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil> > >,0> >
如果你有很多这样的结构,那么 PDB 文件会增长得很快,直到链接器拒绝链接你的应用程序(显然,PDB 文件有 1 GB 的限制)。
一种解决方案可能是创建模板化实例的子类,如下所示:
class BookChapterReader : public std::tuple<Book,Chapter,Reader>
{
};
这将严重缩短符号。现在上面提到的是:
std::_Tree<std::_Tmap_traits<Library,BookChapterReader,std::less<Library>,std::allocator<std::pair<Library const ,BookChapterReader> >,0> >
但是,通过使用继承,我们引入了可能向继承的类添加数据的风险,并且我们可能需要引入一个虚拟析构函数(在这种情况下我不想要它)。
看来C++(或者Visual Studio?)有一个限制:
- 如果我只使用 typedef,符号会变得太大
- 如果我使用继承,我似乎想扩展 std::tuple,但我不想这样做
难道没有一种更简洁的方法可以在不使用继承的情况下“重命名”模板实例化吗?
【问题讨论】:
-
我不认为VS2010支持它,我也不知道它是如何处理PDB“扩展”的,否则你可以尝试例如
using BookChapterReader = std::tuple<Book, Chapter, Reader>; -
一个类型需要有一个唯一的名字,所以不同的 TU 知道他们在谈论同一个东西。因此,缩短调试符号的唯一机会是创建新的/不同的类型(注意 typedef/using 只会创建别名)。
-
@JoachimPileborg
using X = foo;是 equivalent 到typedef foo X;,所以差异会令人惊讶(但尝试并确实看到并不需要太多成本)。 @Patrick 顺便说一句,让你的问题变得更糟的是 VS2010 没有真正支持 C++11 并使用“std::tr1::tuple<Book,Chapter,Reader,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>”来表示真正应该简单的“std::tuple<Book,Chapter,Reader>”(我认为 VS2012 或更高版本确实如此)用途)。但这不是答案,我知道... -
@gx_,我知道。 VS2010 的实现甚至被限制在 10 个维度。这就是我使用 boost::fusion::vector 而不是 std::tuple 的原因,但我想让这个例子足够简单。
标签: c++ visual-studio-2010 templates pdb-files