使用泛型将字符串的 C++ 映射到自定义 class
C++ map of string to custom class with generics
过去几天我一直在尝试解决我在 C++ 中遇到的这个问题。这可能是微不足道的,但我找不到解决方案,在网上搜索也无济于事,所以我会在这里问。
我有一个 C++ 包装器 Singleton
class、一个 superclass 和一些 subclasses。我需要 subclasses 的实例是单例,所以我使用了 here 提出的解决方案,因为它最适合我的需要。我需要一个映射作为从字符串到正确子 class 的寄存器。为了使它具体,这里是代码:
// The Singleton class
template <typename T>
class Singleton
{
public:
static T* Instance()
{
if (s_instance == NULL) { s_instance = new T(); }
return s_instance;
}
protected:
static T* s_instance;
}
// Superclass
class MySuperclass
{
public:
inline LPCSTR GetName() { return m_name; }
virtual ~MySuperclass() { }
protected:
LPCSTR m_name;
MySuperclass(LPCSTR name) { m_name = name; }
}
// Example subclass
class MySubclass : public MySuperclass
{
// subclass stuff
}
现在,我已经尝试了很多东西,让我展示一下我尝试过的所有东西:
// Where the problems begin
class MyRegister
{
public:
static void Register()
{
Singleton<MySubclass> mySubclassSingleton;
LPCSTR name = Singleton<MySubclass>::Instance()->GetName();
s_classes.insert(std::make_pair(name, mySubclassSingleton));
}
private:
static std::unordered_map<LPCSTR, Singleton<MySuperclass>> s_classes;
}
这是我坚持使用的版本,它在 insert
上给出了一个错误:
E0304 no instance of overloaded function "std::map<_Kty, _Ty, _Pr, _Alloc>::insert [with _Kty=LPCSTR, _Ty=Singleton<MySuperclass>, _Pr=std::less<LPCSTR>, _Alloc=std::allocator<std::pair<const LPCSTR, Singleton<MySuperclass>>>]" matches the argument list
我尝试使用 std::pair
而不是 std::make_pair
,将地图的定义更改为:
template <class T : public MySuperclass>
std::unordered_map s_classes<LPCSTR, Singleton<T>> s_classes;
但无济于事,因为第一个导致相同的错误(也使用 []
运算符给我带来了 [name]
与 no operator matches these operands
的问题),第二个导致类型错误。
就目前而言,我需要 classes 是单例,并确保它们是单例,并且我需要一个寄存器来链接一个唯一的字符串,该字符串将 class 标识到它的单例.任何人都可以解释为什么这是不可能的,或者 C++ 中是否有类似 Java 的 <? extends MySuperclass>
的东西可以在这里工作?
template <class T : public MySuperclass>
std::unordered_map s_classes<std::string, Singleton<T>> s_classes;
不是有效的 C++。
但是你可以简单地做一个std::unordered_map<std::string, MySuperclass*> s_classes
。
我们的查找映射不需要知道 Singleton
模式,它只需要映射到指向相应子类的指针。我们必须使用 std::string
或 std::wstring
作为键,否则键之间将使用指针比较,而不是字符串比较。或者,我们可以提供自定义比较运算符。
Singleton
本身也可以简化。 static
局部变量在第一次使用函数时初始化,这正是我们想要的行为。
template <typename T>
class Singleton
{
static T *Instance()
{
static T instance{};
return &instance;
}
}
我们之前对 new
的使用本来就是内存泄漏,因为从未调用过 delete
。
现在,我们也可以相应地更新或MyRegister
。
class MyRegister
{
public:
static void Register()
{
MySubclass *instance = Singleton<MySubclass>::instance();
s_classes.emplace(instance->GetName(), instance);
}
private:
static std::unordered_map<std::string, MySuperclass*> s_classes;
}
过去几天我一直在尝试解决我在 C++ 中遇到的这个问题。这可能是微不足道的,但我找不到解决方案,在网上搜索也无济于事,所以我会在这里问。
我有一个 C++ 包装器 Singleton
class、一个 superclass 和一些 subclasses。我需要 subclasses 的实例是单例,所以我使用了 here 提出的解决方案,因为它最适合我的需要。我需要一个映射作为从字符串到正确子 class 的寄存器。为了使它具体,这里是代码:
// The Singleton class
template <typename T>
class Singleton
{
public:
static T* Instance()
{
if (s_instance == NULL) { s_instance = new T(); }
return s_instance;
}
protected:
static T* s_instance;
}
// Superclass
class MySuperclass
{
public:
inline LPCSTR GetName() { return m_name; }
virtual ~MySuperclass() { }
protected:
LPCSTR m_name;
MySuperclass(LPCSTR name) { m_name = name; }
}
// Example subclass
class MySubclass : public MySuperclass
{
// subclass stuff
}
现在,我已经尝试了很多东西,让我展示一下我尝试过的所有东西:
// Where the problems begin
class MyRegister
{
public:
static void Register()
{
Singleton<MySubclass> mySubclassSingleton;
LPCSTR name = Singleton<MySubclass>::Instance()->GetName();
s_classes.insert(std::make_pair(name, mySubclassSingleton));
}
private:
static std::unordered_map<LPCSTR, Singleton<MySuperclass>> s_classes;
}
这是我坚持使用的版本,它在 insert
上给出了一个错误:
E0304 no instance of overloaded function "std::map<_Kty, _Ty, _Pr, _Alloc>::insert [with _Kty=LPCSTR, _Ty=Singleton<MySuperclass>, _Pr=std::less<LPCSTR>, _Alloc=std::allocator<std::pair<const LPCSTR, Singleton<MySuperclass>>>]" matches the argument list
我尝试使用 std::pair
而不是 std::make_pair
,将地图的定义更改为:
template <class T : public MySuperclass>
std::unordered_map s_classes<LPCSTR, Singleton<T>> s_classes;
但无济于事,因为第一个导致相同的错误(也使用 []
运算符给我带来了 [name]
与 no operator matches these operands
的问题),第二个导致类型错误。
就目前而言,我需要 classes 是单例,并确保它们是单例,并且我需要一个寄存器来链接一个唯一的字符串,该字符串将 class 标识到它的单例.任何人都可以解释为什么这是不可能的,或者 C++ 中是否有类似 Java 的 <? extends MySuperclass>
的东西可以在这里工作?
template <class T : public MySuperclass>
std::unordered_map s_classes<std::string, Singleton<T>> s_classes;
不是有效的 C++。
但是你可以简单地做一个std::unordered_map<std::string, MySuperclass*> s_classes
。
我们的查找映射不需要知道 Singleton
模式,它只需要映射到指向相应子类的指针。我们必须使用 std::string
或 std::wstring
作为键,否则键之间将使用指针比较,而不是字符串比较。或者,我们可以提供自定义比较运算符。
Singleton
本身也可以简化。 static
局部变量在第一次使用函数时初始化,这正是我们想要的行为。
template <typename T>
class Singleton
{
static T *Instance()
{
static T instance{};
return &instance;
}
}
我们之前对 new
的使用本来就是内存泄漏,因为从未调用过 delete
。
现在,我们也可以相应地更新或MyRegister
。
class MyRegister
{
public:
static void Register()
{
MySubclass *instance = Singleton<MySubclass>::instance();
s_classes.emplace(instance->GetName(), instance);
}
private:
static std::unordered_map<std::string, MySuperclass*> s_classes;
}