Фабричная функция - шаблон

317
13 июня 2022, 06:50

Тренируюсь, и хотел реализовать фабричную функцию - шаблон, принимающую любое количество аргументов (вариативность). Алгоритм: шаблон принимает типы - тип создаваемого класса, и тип пакет параметров. В параметрах сам пакет параметров. Создаваемые классы находятся в цепочке наследования. Код:

#include <memory>
class Base
{
public:
    virtual void run() = 0;
};
class A : public Base
{
public:
    A(int& a, int& b) {}
    void run() override {}
};

class B : public Base
{
public:
    B(int& a) {}
    void run() override {}
};
enum class ClassConst : int
{
    _A = 0,
    _B
};
template<ClassConst mt, class... Args>
auto creator(Args&&... args)
{
    std::unique_ptr<Base> result(nullptr);
    if(ClassConst::_A == mt)
        result = std::make_unique<A>(args...);
    else if(ClassConst::_B == mt)
        result = std::make_unique<B>(args...);
    return result;
};
int main()
{
    creator<ClassConst::_A>(45, 88);
    creator<ClassConst::_B>(69);
}

Код не компилируется:

  1. Конструктор B с двумя аргументами int не найден
  2. Конструктор перемещения A не может преобразовать 1 аргумент int в const A&

Хотелось бы понять, почему так происходит.

Answer 1

Тут проблема в том, что при инстанцировании creator всегда инстанцируются обе ветви - if и else и одна из них будет невалидной. Чтобы это исправить следует использовать if constexpr

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

template< ClassConst x_class_id > class
TypeByIdImpl;
template<> class
TypeByIdImpl<ClassConst::_A> final { public: using type = A; };
template<> class
TypeByIdImpl<ClassConst::_B> final { public: using type = B; };
template< ClassConst x_class_id > using
TypeById = typename TypeByIdImpl<x_class_id>::type;
template<ClassConst id, typename ... Args>
auto creator(Args && ... args)
{
    return ::std::unique_ptr<Base>{::std::make_unique<TypeById<id>>(args...)};
};

Еще обычно имеет смысл форвардить аргументы.

READ ALSO
Какие бывают виды шаблонов (templates) в C++?

Какие бывают виды шаблонов (templates) в C++?

В c++ есть шаблоны классов (сюда же структур) и функцийЯ узнал, что это не все виды шаблонов (templates), но нигде не могу найти остальные

237
Порядок байтов при чтении файла

Порядок байтов при чтении файла

Почему при чтении бинарного файла нет опции для указания порядка байтов? Есть только binary режим, но нет LE или BE

314
Лабораторная работа по динамичному массиву

Лабораторная работа по динамичному массиву

Задание:Найти наименьший элемент матрицы и записать в строку, где находится этот элемент, '10'Размер матрицы вводить с клавиатуры, а элементы...

310
Вызвано исключение по адресу (msvcp140d.dll)

Вызвано исключение по адресу (msvcp140d.dll)

Программа определяет систему счисления по префиксам если 0x или 0X, то 16 СС, так же с 2 ССКод одинаковый для 16 СС и для 2 СС, но при переходе на метку...

184