如何在不创建每种类型的实例的情况下迭代类型列表?
在我的示例中,我有一个带有方法getByName
的父类,它返回子类的实例。由于无法创建typedef数组,因此getByName
方法完全被破坏。使这项工作的最佳方法是什么?
一种解决方案是创建一个name
指针数组,但如果有多个变量(不仅仅是name
)我想要检查它,这会变得混乱。
我基本上想要一个使用循环而不是一系列if语句的干净解决方案。
#include <string>
struct Number {
Number(const std::string &name) :name(name) {}
// fix me!
static Number* getByName(const std::string &name) {
typedef types[] = {
One,
Two,
Three,
}
for (int i = 0; i < 3; ++i) {
if (name == types[i]::name)
return new types[i]();
}
return nullptr;
}
const std::string name;
};
struct One :Number {
One() :Number(name) {}
const static std::string name;
};
struct Two :Number {
Two() :Number(name) {}
const static std::string name;
};
struct Three :Number {
Three() :Number(name) {}
const static std::string name;
};
const std::string One::name = "one";
const std::string Two::name = "two";
const std::string Three::name = "three";
答案 0 :(得分:3)
您可以按照以下方式实施工厂
template <typename T>
static std::pair<std::string, std::function<Number*()>> register_helper()
{
return { T::name, []() { return new T{}; }};
}
static Number* getByName(const std::string &name) {
static const std::map<std::string, std::function<Number*()>> factories = {
register_helper<One>(),
register_helper<Two>(),
register_helper<Three>()
};
auto it = factories.find(name);
if (it == factories.end()) {
return nullptr;
} else {
return it->second();
}
}
答案 1 :(得分:1)
您无法以有意义的方式直接存储类型;但是,您可以存储指向工厂函数的指针,这应该同样有用:
yourView.codedSundayButtons(firstButton: ButtonSunChore1R, secondButton: ButtonSunChore1Y)
答案 2 :(得分:0)
尝试使用比之前的音高更简单的东西,并假设getByName不会经常使用不受支持的值调用。
template <typename TYPE>
Number * factory()
{
return new TYPE();
}
static const std::map<std::string, Number*(*)()> factories =
{
{One::name, factory<One>},
{Two::name, factory<Two>},
{Three::name, factory<Three>}
};
static Number* getByName(const std::string &name)
{
try
{
return factories.at(name)();
}
catch (std::out_of_range &e)
{
// Log factory called with bad name as a hint that the programmer
// should check calling code.
return nullptr;
}
}
但是如果带有错误名称的调用是预期的用例,那么困难的方法比处理异常要便宜得多。
static Number* getByName(const std::string &name)
{
auto factory = factories.find(name);
if (factory != factories.end())
{
return factory->second();
}
return nullptr;
}