Я следовал этому руководству / примеру по созданию саморегистрационного типа в 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 ++), она завершится неудачно, но если я поместу эту реализацию в файл, которыйсвязанный после , он работает как задумано.Я все еще не уверен, как заставить это работать универсально все же.