mercredi 5 avril 2017

Factory and singleton patterns: undefined reference

I have tried to understand what's going on in my situation from other questions in this site, but I haven't really found a good answer. I tried most of the suggestions I found but still get the same error.

I am trying to implement a factory based on a singleton and the CRTP. So I have a Singleton class, define in Singleton.h:

template<class T>
class Singleton
{
public:
  static T &instance()
  {
    static T one;
    return one;
  }

  Singleton(const Singleton &) = delete;
  Singleton(Singleton &&) = delete;
  Singleton &operator=(const Singleton &) = delete;
protected:
    Singleton() = default;
};

I also have a Factory class, defined and implemented in Factory.h. The factory creates objects of a hierarchy whose base class is, for the purposes of this question, Object. These objects all have a constructor accepting a double.

class Factory : public Singleton<Factory>
{
    friend class Singleton<Factory>; // to access constructor
public:
    using createFunction = Object *(*)(double);

    void registerObject(const std::string &, createFunction);
    Object *createObject(const std::string &, double) const;
private:
    Factory() = default;
    std::map<std::string, createFunction> theCreatorFunctions;
};

void Factory::registerObject(
    const std::string &ObjectId,
    createFunction creatorFunction)
{
    theCreatorFunctions.insert(
        std::pair<std::string, createFunction>(
            ObjectId, creatorFunction));    
}

Object *Factory::createObject(
    const std::string &ObjectId, double a) const
{
    auto it = theCreatorFunctions.find(ObjectId);
    if (it == theCreatorFunctions.end())
    {
        std::cout << ObjectId << " is an unknown object."
                  << std::endl;
        return nullptr;
    }
    return (it->second)(a);
}

Finally, I have a "helper" class that registers new types of Objects into the factory. Each time a new inherited object is created, say ObjectDerived, I add (in the .cpp file where ObjectDerived is implemented):

FactoryHelper<ObjectDerived> registerObjectDerived("ObjectDerived");

This creates an object of type FactoryHelper<ObjectDerived>, whose constructor handles the registration in the factory. FactoryHelper is defined (and implemented) in FactoryHelper.h:

template<class T>
class FactoryHelper
{
public:
    FactoryHelper(const std::string &);
    static Object *create(double);
};

template<class T>
FactoryHelper<T>::FactoryHelper(const std::string &ObjectId)
{
    Factory &theFactory = Factory::instance(); // the one and only!
    // if it doesn't exist at this point, it is created.
    theFactory.registerObject(ObjectId, FactoryHelper<T>::create);
}

template<class T>
Object *FactoryHelper<T>::create(double a)
{
    return new T(a);
}

So the problem that I have is that I get a bunch of undefined references to Factory::instance(), basically one for each type of object in the hierarchy.

I actually tried to do all of this in the same file, including Singleton, Factory and FactoryHelper, but still get the same errors.

Aucun commentaire:

Enregistrer un commentaire