Как я могу исправить свой Factory Pattern, чтобы устранить эти ошибки компиляции? - PullRequest
0 голосов
/ 25 ноября 2010

Моя цель - создать систему, в которой я могу предоставить строковое имя класса во время выполнения и заставить его по очереди возвращать экземпляр этого класса. Выполняя поиск в stackoverflow, я наткнулся на пример, который, кажется, делает именно то, что я пытаюсь выполнить, хотя в настоящее время я не могу его правильно скомпилировать. Следующее основано на этом коде:

//LevelObject.h    
#pragma once

#include <map>
#include <string>

class LevelObject
{
    protected:
        int ID;

    public:
        template<class T> static LevelObject* createT(void)
        {
            return new T(0);
        }

        LevelObject(void);
        ~LevelObject(void);
};

struct BaseFactory
{
    typedef std::map<std::string, LevelObject*(*)()> map_type;

    static LevelObject* createInstance(const std::string& s)
    {
        map_type::iterator it = getMap()->find(s);
        if(it == getMap()->end())
        {
            return 0;
        }
        return it->second();
    }

    private:
        static map_type* objectMap;

    protected:
        static map_type* getMap()
        {
            if(!objectMap)
            {
                objectMap= new map_type;
            } 
            return objectMap; 
        }
};

template<class T>
struct DerivedRegister : BaseFactory
{ 
    DerivedRegister(const std::string& s)
    { 
        getMap()->insert(std::make_pair( s, &LevelObject::createT<T> ));
    }
};


//Item.h
#pragma once

#include "LevelObject.h"

class Item :
    public LevelObject
{
    int ID;
    static DerivedRegister<Item> reg;

public:
    Item(int id);
    ~Item(void);
};


//Item.cpp
#include "Item.h"

Item::Item(int id)
{
    ID = id;
}

Item::~Item(void)
{
}

DerivedRegister<Item> Item::reg("item");

Логика заключается в том, что производные объекты, то есть Item, зарегистрируют строку и ссылку на функцию, которая возвращает свой экземпляр. При вызове createInstance он будет принимать введенную пользователем строку и использовать карту для определения возвращаемого объекта.

К сожалению, этот код неправильно компилируется и выдает следующие ошибки:

Ошибка 1, ошибка C2752: 'std :: tr1 :: _ Remove_reference <_Ty>': более одной частичной специализации соответствует списку аргументов шаблона

Ошибка 2, ошибка C2528: 'аннотация декларатор ': указатель на ссылку нелегальный c: \ program files \ microsoft визуальная студия 10.0 \ vc \ include \ type_traits 965

Ошибка 3, ошибка C2528: «тип»: указатель ссылка на недопустимую программу c: \ файлы \ Microsoft Visual Studio 10.0 \ vc \ include \ type_traits 349

Если кто-то может помочь сгладить эти ошибки, я был бы очень признателен. Или, может быть, я вначале ошибаюсь, поэтому если кто-то считает, что я должен идти совсем в другом направлении, пожалуйста, дайте мне знать.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 24 сентября 2011

Прошло много времени с тех пор, как этот вопрос был опубликован, но так как ответа нет, и я тоже споткнулся, я решил добавить один.Я скопировал тот же заводской код, что и вы (из ответа StackOverflow здесь ), и у меня возникла та же проблема.Я нашел решение в этом ответе StackOverflow.

Оказывается, Visual Studio 2010 (который, как я предполагаю, вы используете) имеет проблему с std::make_pair.Просто используйте std::pair<std::string,LevelObject*(*)()> вместо этого, и вам будет хорошо.По крайней мере, это решило точно такую ​​же проблему для меня.

0 голосов
/ 25 ноября 2010

Я добавил пустые тела в конструктор и деструктор класса LevelObject:

LevelObject(void) { }
~LevelObject(void) { }

Затем объявил статическую переменную-член map класса BaeFactory:

BaseFactory::map_type* BaseFactory::map;

и код, скомпилированный без ошибок в GCC и Visual Studio.

...