Как создать конкретный класс из шаблонного класса

Скажем, у меня есть шаблон класса:

template <typename T> class StringDeque:
public std::deque<T>
{
public:

    ...

private:
    typedef std::deque<T> BaseClass; 
};

Скажи, я хочу создать конкретный класс ArrayString где T=std::string, Как правильно добиться этого:

определять

#define ArrayString StringDeque<string>

ЬурейеЕ

typedef StringDeque < string > ArrayString;

наследование

class ArrayString :
    public StringDeque < string > {};

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

3 ответа

Решение

Правильные способы:

typedef std::deque<std::string> StringDeque;
using StringDeque = std::deque<string>;

Тем не менее, вот еще несколько замечаний по вашему вопросу:

Вы написали:

template <typename T> class StringDeque: public std::deque<T> // ...

std Контейнерные классы не подразумеваются как базовые классы. Это означает, что они не должны наследоваться от (а наследование от них - UB).

Когда вы хотите использовать std Функциональность контейнера в другом классе, ответ всегда должен быть инкапсуляции. Это означает, что правильный способ использовать функциональность std::queue в ваших классах:

template<typename T> class StringDequeue {
    std::deque<T> storage;
public:
    // add interface here that uses storage
};

Вы также предложили это:

#define ArrayString StringDeque<string>

Пожалуйста, никогда не используйте define для объявления типа. Это работает, но имеет свои подводные камни и считается плохой практикой в ​​C++.

Вы хотите дать имя определенному типу (который является экземпляром шаблона). C++ способ давать имена (псевдонимы) типам с помощью typedef:

typedef StringDeque<string> ArrayString;

Или, начиная с C++11, с объявлением псевдонима:

using ArrayString = StringDeque<string>;

Примечание: когда вы думаете об этом, это, как правило, помогает думать с точки зрения правильной терминологии шаблона. У вас нет "шаблона класса" (класс со специальными свойствами), у вас есть "шаблон класса" (шаблон для создания классов). Шаблон не является типом; его экземпляры есть.

Создать псевдонимы типа с typedef или (начиная с C++ 11) using:

typedef StringDeque<std::string> ArrayString;
using ArrayString = StringDeque<std::string>;

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

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

Другие вопросы по тегам