在c ++中创建类型向量

时间:2018-05-22 13:01:13

标签: c++ type-conversion rtti

我有几个类,每个类都有一个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);
 }     

5 个答案:

答案 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>();
}

工作示例:https://ideone.com/urh7h6

答案 3 :(得分:0)

由于C ++是一种静态类型的语言,你可以选择任意类型做一组固定的东西,或者让一组固定的类型做任意事情,但不能同时做两件事。

std::functionstd::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