简体   繁体   English

C ++:编译未使用的类

[英]C++: Compiling unused classes

There is a pattern that I like using for implementing factory classes that goes as follows (taken from my answer to this question): 我喜欢使用一种模式来实现工厂类,该模式如下所示(摘自对此问题的回答):

class Factory
{
public:
    template<class DerivedType>
    DerivedType::CreatedType *createType()
    {
        DerivedType::CreatedType *r = (DerivedType::CreatedType) (*(m_creators[DerivedType::id]))();
        return r;
    }
protected:
    static std::map<int,void *(*)()> m_creators;
};

std::map<int,void *(*)()> Factory::m_creators = std::map<int,void*(*)()>();

template<class Derived, class CreatedType>
class CRTPFactory : public Factory
{
    typedef typename CreatedType CreatedType;
public:
    static bool register() 
    {
        Factory::m_creators.push_back(std::make_pair(Derived::id,Derived::create);
        return true;
    }

private:
    static bool m_temp;
};

template<class Derived>
bool CRTPFactory<Derived>::m_temp = CRTPFactory<Derived>::register();

class AFactory : public CRTPFactory<AFactory,A>
{
private:
    static A *create() 
    {
        //do all initialization stuff here
        return new A;
    }

public:
    static const int id = 0;
};

This allows extension of the factory for new types without having to change the factory class. 这允许将工厂扩展为新类型,而不必更改工厂类别。 It also allows for implementing specific creation algorithms for different types without having to change the factory class. 它还允许为不同类型实现特定的创建算法,而不必更改工厂类。 There is a major problem with this pattern though. 但是,这种模式存在一个主要问题。 The class AFactory is never used explicitly. 永远不会显式使用AFactory类。 It registers its creator function at load time through CRTPFactory's member temp. 它在加载时通​​过CRTPFactory的成员临时寄存器注册其创建者函数。 This might be a little complicated to understand but it's very easy to use. 这可能有点难以理解,但是非常易于使用。 The problem is AFactory isn't compiled so it's static parameters aren't initialized at load time. 问题在于AFactory未编译,因此其静态参数未在加载时初始化。 My question is, is it possible to force the compiler (I'm using VS 2012 but answers for GCC are also good) to compile AFactory without ever explicitly creating an instance of it? 我的问题是,是否可以强制编译器(我使用的是VS 2012,但对GCC的回答也不错)而无需显式创建其实例即可编译AFactory吗? A solution that I use in VS is to dllexport AFactory, that way the compiler compiles the class even though it doesn't know of anyone instantiating it. 我在VS中使用的一种解决方案是dllexport AFactory,这样编译器即使不知道有人实例化该类也可以编译该类。 This is because it assumes some other dll might instantiate it. 这是因为它假定其他一些dll可能将其实例化。 The problem with this solution is that the factory class must be implemented in a separate dll as the rest of the code. 此解决方案的问题在于,工厂类必须作为其余的代码在单独的dll中实现。 And also this doesn't work on GCC. 而且这在GCC上不起作用。

Inheriting from CRTPFactory<AFactory,A> causes implicit instantiation of the class, but not the definitions of its members. CRTPFactory<AFactory,A>继承会导致类的隐式实例化,但不会导致其成员的定义。

[temp.inst]

The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, static data members and member templates; 类模板专业化的隐式实例化导致类成员函数,成员类,静态数据成员和成员模板的声明而不是定义或默认参数的隐式实例化;

Instead of inheriting from CRTPFactory<AFactory,A> , you can simply explicitly instantiate the m_temp member. 不必从CRTPFactory<AFactory,A>继承,而是可以显式实例化m_temp成员。

template bool CRTPFactory<AFactory,A>::m_temp;

For reference, here's the modified example (in a form that compiles): 作为参考,这是修改后的示例(以编译的形式):

#include <map>

class Factory
{
public:
    template<class DerivedType, class CreatedType>
    CreatedType *createType()
    {
        CreatedType *r = (CreatedType) (*(m_creators[DerivedType::id]))();
        return r;
    }
protected:
    static std::map<int,void *(*)()> m_creators;
};

std::map<int,void *(*)()> Factory::m_creators = std::map<int,void*(*)()>();

template<class Derived, class CreatedType>
class CRTPFactory : public Factory
{

public:
    static bool register_() 
    {
        Factory::m_creators.insert(std::make_pair(Derived::id,Derived::create));
        return true;
    }

  static bool m_temp;
};

template<class Derived, class CreatedType>
bool CRTPFactory<Derived, CreatedType>::m_temp = CRTPFactory<Derived, CreatedType>::register_();

struct A
{
};

class AFactory
{
public:
    static void *create() 
    {
        //do all initialization stuff here
        return new A;
    }

public:
    static const int id = 0;
};

template bool CRTPFactory<AFactory,A>::m_temp;

Static class member should be explicitly created somewhere. 静态类成员应在某处显式创建。

Doing something like this in a cpp file of your choice should work: 在您选择的cpp文件中执行以下操作应该可以:

int AFactory::id = 0

You're mistaken in your assumption. 你误会了你的假设。 class AFactory is definitely compiled. class AFactory肯定已编译。 Quite a few times, probably, since it's in a header. 因为它在标题中,所以可能有好几次了。

Your real problem is probably that class AFactory is not registered . 您真正的问题可能是未注册 class AFactory Why would it be? 为什么会这样呢? Which statement would cause it to be? 会导致以下哪种说法? Every statement is ultimately called either from main() or from the initializer of a global variable. 最终,每个语句都可以从main()或全局变量的初始化程序中调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM