Специализация шаблонного класса

133
13 декабря 2018, 05:10

Есть шаблонный класс:

template <typename T>
class CSerializer {
public:
    void write(std::ostream &stream, const T &value) const;
    void  read(std::istream &stream, T &value) const;
};

Предполагается, что инстанцирование объектов данного класса будет выполняться только для PDT типов (int, unsigned, char и т.п.).

Для остальных типов предполагается наличие специализаций данного класса, например, для типа std::string:

template <>
class CSerializer<std::string> {
public:
    void write(std::ostream &stream, const std::string &str) const;
    void  read(std::istream &stream, std::string &str) const;
};

Далее. У нас есть интерфейс ISerializable:

class ISerializable {
public:
    virtual ~ISerializable() = default;
public:
    virtual void    write_binary(std::ostream &stream) const = 0;
    virtual void     read_binary(std::istream &stream) = 0;
    virtual size    serialized_size() const noexcept = 0;
};

, а так же множество классов, которые от него наследуются. Я хотел специализировать класс CSerializer для типа ISerializable, вроде:

template <>
class CSerializer<ISerializable> {
public:
    void write(std::ostream &stream, const ISerializable &obj) const;
    void  read(std::istream &stream, ISerializable &obj) const;
};

И это не заработало :) Почему не заработало - я понимаю. Вопрос: можно ли написать такую специализацию класса CSerializer, которая бы инстанцировалась, когда T - класс-наследник ISerializable?

Я знаю как это сделать через ф-ию, вроде:

template <typename T, typename Enable = void>
CSerializer<T>* make_serializer() { ... }
template <typename T, typename std::enable_if<std::is_base_of< ... >>::value>
CSerializer<ISerializable>* make_serializer() { ... }

Но пусть это будет "запасным" вариантом.

UPD: подсказали, что в C++20 для этого идеально подходят концепты. Создал еще один вопрос.

Answer 1

Все точно так же, как с функцией:

template <typename T, typename Void = void>
class CSerializer
{
    static_assert(std::is_void_v<Void>);
    ...
};
template <typename T>
class CSerializer<T, std::enable_if_t<std::is_base_of_v<ISerializable, T>>>
{
    ...
};
Answer 2

ну как вариант, можно сделать:

template<typename _T>
using SerializerType = CSerializer<typename std::conditional<std::is_base_of<ISerializable, _T>::value, ISerializable, _T>::type>;
READ ALSO
Генерация больших целых значений

Генерация больших целых значений

Как сгенерировать значения, допустим от 10000 до 99999? Используя Mathrandom() проскакивают четырех-,шести- значные

173
Помогите найти ошибку в методе

Помогите найти ошибку в методе

Есть массив заполненный числами от 1 до 100 с пропущенным числом 46, путем сложения первого и последнего элемента идет поиск пропущенного элемента,...

267
Как работает if и else?

Как работает if и else?

В приложении есть чекбокс, и если пользователь устанавливает галочку то мы должны считать цену чашки кофе не по 5$, а по 6$

209