создание вектора типа в с ++ - PullRequest
0 голосов
/ 22 мая 2018

У меня есть несколько классов, у каждого из которых есть идентификатор, и идентификатор передается классу в качестве параметра шаблона:

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 голосов
/ 22 мая 2018

Поскольку язык 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();
}
0 голосов
/ 22 мая 2018

Если вам нужно только создать объект, достаточно реализовать функцию создания шаблона, например:

template<int ID>
Base<ID> Create()
{
    return Base<ID>();
}

, а затем использовать ее:

auto obj1 = Create<1>();
auto obj2 = Create<2>();
// etc

Рабочий пример: https://ideone.com/urh7h6

0 голосов
/ 22 мая 2018

В качестве эскиза:

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].

0 голосов
/ 22 мая 2018

Если я правильно понимаю, вы хотите, чтобы карта создавала различные типы в соответствии с заданным числом.

Если это так, то код должен выглядеть примерно так:

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
0 голосов
/ 22 мая 2018

То, что вы ищете, это либо шаблон 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
...