Как создать шаблонный класс с помощью конструкторов не по умолчанию - PullRequest
0 голосов
/ 27 октября 2018

Пожалуйста, рассмотрите следующий пример:

class Generator {
public:
    Generator(int n)
        : m_n(n)
    {
    }

    int f()
    {
        return m_n;
    }
private: 
    int m_n;
};

template<class BaseClass>
class Transformer : public BaseClass
{
public:
    Transformer(int mult, int add)
        : m_mult(mult)
        , m_add(add)
    {

    }

    int f()
    {
        return BaseClass::f() * m_mult + m_add;
    }

private:
    int m_add;
    int m_mult;
};

Воображение: существует больше классов Generator, которые имеют разные аргументы в своих конструкторах.Теперь я хочу создать экземпляр класса, состоящий из обоих передавая все необходимые параметры.Поэтому я попробовал следующее, но Generator явно не распознается как базовый класс:

class TG : public Transformer<Generator>
{
public:
    TG(int n, int mult, int add)
        : Generator(n)              // error C2614: 'TG': illegal member initialization: 'Generator' is not a base or member
        , Transformer(mult, add)
    {}
};

TG t(n,mult,add);

Затем я попробовал специализацию шаблона:

template<> Transformer<Generator>::Transformer(int n, int mult, int add)    // error C2244: 'Transformer<Generator>::Transformer': unable to match function definition to an existing declaration
    : Transformer(mult,add)
    , Generator(n)
{};

Transformer<Generator> t(n,mult,add);

Как создать экземпляр шаблона,у которого есть конструкторы не по умолчанию?

1 Ответ

0 голосов
/ 27 октября 2018

Воображение: существует больше классов-генераторов, которые имеют разные аргументы в своих конструкторах. Теперь я хочу создать экземпляр класса, состоящий из обоих передавая все необходимые параметры

Мне кажется, что если вы можете использовать хотя бы C ++ 11, то вам нужен вариадический шаблонный конструктор, написанный следующим образом

template <typename ... As>
Transformer (int mult, int add, As && ... as)
    : BaseClass{std::forward<As>(as)...}, m_mult{mult}, m_add{add}
 { }

Идея состоит в том, что конструктор сначала получает значения для членов (m_mult и m_add), которые когда-либо требуются, а затем список переменных аргументов для базового класса (с идеальной пересылкой; не обязательно, но может быть полезно, вообще говоря). Этот порядок необходим, потому что аргумент списка выводов должен быть в последней позиции.

Конструктор TG становится

template <typename ... As>
TG (int mult, int add, As && ... as)
   : Transformer{mult, add, std::forward<As>(as)...}
 { }
...