'_Wherenode был nullptr' при добавлении к статическому std :: map - PullRequest
0 голосов
/ 09 апреля 2019

Я следовал этому руководству / примеру по созданию саморегистрационного типа в C ++ 17.Но я столкнулся с проблемой: при попытке регистрации типа моя программа завершается с ошибкой read access violation. _Wherenode was nullptr. Эта ошибка возникает в методе std::_Tree<std::Tmap_traits<...>::_Lbound стандартной библиотеки.

Это мой исходный код, почтиидентичный описанному на странице (с некоторыми изменениями для исправления ошибок в исходном коде:)

class Entity { ... }; // Contents irrelevant

class EntityTypeFactory {
public:
    using TCreateMethod = std::function<Entity* ()>;

    EntityTypeFactory() = delete;

    static Entity* Create(const std::string& type);

    static bool Register(const std::string& name, TCreateMethod func);

private:
    static std::map<std::string, TCreateMethod> s_methods;
};

#define REG_ENT(TYPE) class TYPE##Creator { private: static bool s_created; }; \
bool TYPE##Creator::s_created = EntityTypeFactory::Register(#TYPE, []() -> Entity* { return new TYPE(); });


std::map<std::string, EntityTypeFactory::TCreateMethod>* EntityTypeFactory::s_methods;

Entity* EntityTypeFactory::Create(const std::string& type)
{
    if (s_methods == nullptr) return nullptr;

    return (*s_methods)[type]();
}

bool EntityTypeFactory::Register(const std::string& name, TCreateMethod func)
{
    if (s_methods == nullptr)
        s_methods = new std::map<std::string, TCreateMethod>();

    (*s_methods)[name] = func;
    return true;
}

class Foo : public Entity {}; // Contents irrelevant

REG_ENT(Foo)

Редактировать: Это, похоже, связано с порядком линковки, как будто яПоместить мою тестовую реализацию Foo в исходный файл, который произойдет раньше, чем Entity при сортировке в алфавитном порядке (так как это похоже на способ выбора порядка ссылок в VC ++), она завершится неудачно, но если я поместу эту реализацию в файл, которыйсвязанный после , он работает как задумано.Я все еще не уверен, как заставить это работать универсально все же.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...