如何强制在库中包含"未使用的"对象定义

Edw*_*nge 12 c++ linker

我的问题类似于这些,但似乎并没有完全相关:

如何在链接到可执行文件时强制将对象文件包含在静态库中?

使用MSVC强制符号导出

我得到的是这样的:

struct thingy;
struct container
{
  static container& instance(); // singleton

  int register_thingy(thingy*);
};

struct thingy
{
  virtual ~thingy() {}
  virtual int id() const = 0;
};

//template trick to force registration.
template < typename Derived >
struct registered_thingy : thingy
{
  registered_thingy() : my_id(my_static_id) {} 

  int id() const { return my_id; }
private:
  int my_id;
  static int my_static_id;
}
template < typename Derived >
int registered_thingy<Derived>::my_static_id = 
  container::instance().register_thingy(new Derived);
Run Code Online (Sandbox Code Playgroud)

现在,concrete_thingy.cpp我在一个文件中:

struct my_concrete_thingy : registered_thingy<my_concrete_thingy>
{
  my_concrete_thingy() {} // registered_thingy's constructor not called otherwise
};
Run Code Online (Sandbox Code Playgroud)

当然,上面的内容完全没用,但这里有抽象的真实行为.

当在作为整体编译的应用程序中使用时,这非常有效.现在的问题是,到目前为止,我无法使用这种技术,同时解决collection库中的行为问题.换句话说,我有一个thingys.lib文件包含concrete_thingy.cpp但是当链接到可执行文件时没有发生注册.在collection结束了现有的和工作正常,但它是空的.

现在,这是一个STATIC库,而不是DLL.这可能会稍微改变这个问题,而上述链接中所说的技术似乎并不适用.当然是关于函数的,我不知道如何将它应用于这些C++结构.

我尝试使用#pragma comment以下三行(当然是单独的)中的方法concrete_thingy.cpp,其中没有一个工作:

#pragma comment (linker, "/export:concrete_thingy")
#pragma comment (linker, "/export:concrete_thingy::my_static_id")
#pragma comment (linker, "/export:registered_thingy<concrete_thingy>::my_static_id")
Run Code Online (Sandbox Code Playgroud)

如果concrete_thingy.cpp在可执行文件而不是库中,一切正常.

那么,这是我的问题:

1)我可以做我想做的事情吗?我猜是的,但我只是不知道如何.

2)如果可能的话,我将如何获得MSVC++ 2010呢?

3)如果可能的话,我怎么能以便携的方式做到这一点?

简而言之,我要做的就是创建一个创建抽象实现的抽象工厂.它对这些实现一无所知,这些实现是使用全局初始化技巧注册的.这应该都在一个可以由应用程序链接的静态库中,这些实现应该可以通过该工厂获得.除了他们自己以外,没有人知道这些实现,因此正常的链接导致它们及其注册全局变量消失.

这不完全是我要做的,但它足够接近.

编辑:================================================ ====

看起来这种行为是"按设计".MS认识到无论是否使用它们都会发生造成副作用的物体的构造,它们使用标准中的漏洞,允许它们不包括任何使用的翻译单元:

https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=244410&wa=wsignin1.0&siteid=210

/ OPT:NOREF选项在这种情况下显然没有做任何事情.

Edw*_*nge 6

好吧,另一个回答好的尝试,但最终没有结果.我将使用改装技巧,但其余的似乎是一个红色的鲱鱼; 它是有道理的,因为有问题的模板实际上并没有在其他任何地方使用,所以它没有明确实例化的事实不应该有所作为...全局的声明仍然发生在A翻译单元中,它有副作用......我不认为标准允许它被优化掉.

关于标准的不幸,不说是否需要包括翻译单元是最终的问题.我认为C++ 0x正在对此做些什么,但也许不是......无论如何,MS根本不会包含单元,因为它不会将全局最终包含在可执行文件中,因此没有其他废话发生.

我决定做的,当然还有许多其他方法,就是创建一个文件'tag'变量.然后将该标签分配给可全局访问的功能(它可以分配或分配,或者参考被优化掉).然后必须从可执行文件中调用该函数.

我决定这样做,因为其余的仍然和以往一样.如果我只是编写一个手动注册类型的注册函数,我最终不会最终改变行为.另外,我可以通过这种方式做其他事情......我只需要确保任何可能属于这个fucktardery分类的东西都有一个标签并且可以访问该标签.

我将编写一堆辅助宏来使这个大多无痛.