我有几个类,每个类都有一个ID,Id作为模板参数传递给类:
typedef class1<1> baseClass;
typedef class2<2> baseClass;
typedef class<100> baseClass;
现在我需要一张地图,所以如果我可以将1与Class1和2与Class2相关联,依此类推。
我该如何创建这样的载体?我正在处理一个只有头文件库,因此它应该只是一个标题定义。
我正在寻找与此代码相同的东西(如果有人可以编译它的话):
std::map<int,Type> getMap()
{
std::map<int,Type> output;
output.add(1,class1);
output.add(2,class2);
output.add(100,class100);
}
我的想法是,当我得到输入1时,我创建了一个class1,当我收到2时,我创建了class2。
非常感谢任何建议。
使用这些数据,然后我可以写一个这样的函数:
void consume(class1 c)
{
// do something interesting with c
}
void consume(class2 c)
{
// do something interesting with c
}
void consume(class3 c)
{
// do something interesting with c
}
void consume(int id,void * buffer)
{
auto map=getMap();
auto data= new map[id](buffer); // assuming that this line create a class based on map, so the map provide the type that it should be created and then this line create that class and pass buffer to it.
consume(data);
}
答案 0 :(得分:1)
作为草图:
class BaseClass { virtual ~BaseClass() = default; };
template<std::size_t I>
class SubClass : public BaseClass {};
namespace detail {
template<std::size_t I>
std::unique_ptr<BaseClass> makeSubClass() { return { new SubClass<I> }; }
template<std::size_t... Is>
std::vector<std::unique_ptr<BaseClass>(*)> makeFactory(std::index_sequence<Is...>)
{ return { makeSubclass<Is>... }; }
}
std::vector<std::unique_ptr<BaseClass>(*)> factory = detail::makeFactory(std::make_index_sequence<100>{});
我们通过扩展参数包来填充vector
,因此我们不必手动写出所有100个实例。这样,您Subclass<0>
factory[0]
,Subclass<1>
factory[1]
,Subclass<99>
factory[99]
PATH
。
答案 1 :(得分:1)
如果我理解正确,您希望地图根据给定的数字创建不同的类型。
如果是这样,那么代码看起来应该是这样的:
class Base
{
};
template <int number>
class Type : public Base
{
public:
Type()
{
std::cout << "type is " << number << std::endl;
}
};
using Type1 = Type<1>;
using Type2 = Type<2>;
using Type3 = Type<3>;
using CreateFunction = std::function<Base*()>;
std::map<int, CreateFunction> creators;
int main()
{
creators[1] = []() -> Base* { return new Type1(); };
creators[2] = []() -> Base* { return new Type2(); };
creators[3] = []() -> Base* { return new Type3(); };
std::vector<Base*> vector;
vector.push_back(creators[1]());
vector.push_back(creators[2]());
vector.push_back(creators[3]());
}
输出:
type is 1
type is 2
type is 3
答案 2 :(得分:0)
如果您只需要创建对象,那么实现模板创建器功能就足够了,如:
if (direction == 3 && walk[currenti + 1][currentj] == '.' && (currenti + 1) > 0 && (currenti + 1) < 10)
然后使用它:
template<int ID>
Base<ID> Create()
{
return Base<ID>();
}
答案 3 :(得分:0)
由于C ++是一种静态类型的语言,你可以选择任意类型做一组固定的东西,或者让一组固定的类型做任意事情,但不能同时做两件事。
std::function
和std::variant
体现了这些限制。 std::function
可以使用固定签名调用operator()
任意类型,std::variant
可以使用任意函数访问固定的类型集。
由于您已经说过类型可能是任意的,因此您可能只有一组固定的事情可以使用这种类型(例如consume
)。最简单的方法是将辛勤工作委托给std::function
struct Type
{
template<typename T>
Type(T&& t)
: f{[t = std::forward<T>(t)]() mutable { consume(t); }} {}
std::function<void()> f;
};
void consume(Type& t)
{
t.f();
}
答案 4 :(得分:-1)
您正在寻找的是Stategy模式:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
class A {
public:
A() {}
virtual void doIt() {};
};
class Aa : public A {
public:
Aa() {}
virtual void doIt() {
std::cout << "do it the Aa way" << std::endl;
}
};
class Ab : public A {
public:
Ab() {}
virtual void doIt() {
std::cout << "do it the Ab way" << std::endl;
}
};
class Concrete {
public:
Concrete(std::string const& type) {
if (type == ("Aa")) {
_a.reset(new Aa());
} else if (type == "Ab") {
_a.reset(new Ab());
}
}
void doIt () const {
_a->doIt();
}
private:
std::unique_ptr<A> _a;
};
int main() {
std::vector<Concrete> vc;
vc.push_back(Concrete("Aa"));
vc.push_back(Concrete("Ab"));
for (auto const& i : vc) {
i.doIt();
}
return 0;
}
将输出:
do it the Aa way
do it the Ab way