遍历类型列表
Iterate through a list of types
如何遍历类型列表而不创建每个类型的实例?
在我的示例中,我有一个父类,其方法getByName
返回子类的实例。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";
你可以像下面这样实现你的工厂
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();
}
}
现场演示
不能以有意义的方式直接存储类型;但是,您可以存储指向工厂函数的指针,这应该同样有用:
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct Number;
Number* oneCreator();
Number* twoCreator();
Number* threeCreator();
struct Number {
typedef Number* (*creatorFP)();
typedef map<string, creatorFP> CreatorMap;
static Number* getByName(const string &name) {
// maybe initialise this map somewhere else
CreatorMap creators;
creators.insert(make_pair(string("one"), &oneCreator));
creators.insert(make_pair(string("two"), &twoCreator));
creators.insert(make_pair(string("three"), &threeCreator));
CreatorMap::iterator creator = creators.find(name);
if (creator != creators.end()) {
return (*(creator->second))();
}
return NULL;
}
virtual void f() { cout << "NUMBER" << endl; }
};
struct One : Number {
virtual void f() { cout << "ONE" << endl; }
};
struct Two : Number {
virtual void f() { cout << "TWO" << endl; }
};
struct Three : Number {
virtual void f() { cout << "THREE" << endl; }
};
Number* oneCreator() { return new One(); }
Number* twoCreator() { return new Two(); }
Number* threeCreator() { return new Three(); }
int main() {
Number *two = Number::getByName(string("two"));
two->f();
return 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;
}
相关文章:
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 使用简单类型列表实现的指数编译时间.为什么
- 使用模板类的自定义列表类型中的内存泄漏
- 列表参数的类型定义
- 初始值设定项列表是否只接受使用相同类型的值初始化变量?
- 从类型列表中递归删除重复项会导致编译器堆空间错误 (VS2017)
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 如何使用类型别名从模板化类中隐藏模板列表
- 测试两个类型列表中的所有组合
- 错误:"模板<类_Tp,类_Dp>类 std::unique_ptr"的模板参数列表中参数 1 的类型/值不匹配
- 谷歌测试:模板模板的笛卡尔乘积的类型列表与模板
- 在迭代模板类型列表时无法停止递归
- 将可变参数类型列表的扩展打包为复杂类型的初始值设定项列表 - 合法吗?
- 使用"auto"推断嵌套初始值设定项列表的类型
- lamda 中的不同类型,在捕获列表中引用
- 阅读从 istream 到矢量的不同类型列表
- 在模板元编程中使用列表类型
- 接受泛型列表类型对象的参数
- 删除c++中列表类型的数组的元素
- 在系统列表中列出::集合::通用::列表<T>类型是可能的吗?