Действительно ли частичная специализация шаблона класса является ответом на эту проблему проектирования?

Может заставить его работать с QMAKE_POST_LINK (нужен += вместо =):

QMAKE_POST_LINK += $(COPY_FILE) $shell_path($OUT_PWD)\lib${TARGET}.so $shell_path(<path to the place where I wish the binary to be copied>)
7
задан Johannes Schaub - litb 10 December 2008 в 16:07
поделиться

4 ответа

Это может быть лучше всего сделано с помощью политики для транспортного протокола:

template<typename Transport>
class service : Transport {
public:
    typedef Transport transport_type;

    // common code
    void do_something() { 
        this->send(....);
    }
};

class tcp {
public:
    void send(....) {

    }
};

class udp {
public:
    void send(....) {

    }
};

typedef service<tcp> service_tcp;
typedef service<udp> service_udp;

Обратите внимание, что это также полиморфно. Это назвало полиморфизм времени компиляции. Помещение политики в базовый класс извлечет выгоду из Empty-Base-Class-Optimization. Таким образом, Ваш базовый класс не должен занимать место. При помещении политики, поскольку у участника есть другой недостаток, что всегда необходимо делегировать материал тому участнику, который может стать раздражающим со временем. Книга современный Дизайн C++ описывает этот всесторонний шаблон.

Идеально, транспортный протокол ничего не должен знать о протоколе выше его. Но если по некоторым причинам необходимо получить некоторую информацию об этом, можно использовать crtp шаблон Wiki:

template<template<typename Service> class Transport>
class service : Transport<service> {

    // since we derive privately, make the transport layer a friend of us, 
    // so that it can cast its this pointer down to us. 
    friend class Transport<service>;

public:
    typedef Transport<service> transport_type;

    // common code
    void do_something() { 
        this->send(....);
    }
};

template<typename Service>
class tcp {
public:
    void send(....) {

    }
};

template<typename Service>
class udp {
public:
    void send(....) {

    }
};

typedef service<tcp> service_tcp;
typedef service<udp> service_udp;

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

template class service<tcp>;
template class service<udp>;

Теперь, код, который использует сервис, не должен знать о коде шаблона сервиса, так как тот код уже сгенерирован в объектный файл service.cpp.

12
ответ дан 6 December 2019 в 11:53
поделиться

Я использовал бы любопытный повторяющийся шаблонный шаблон, иначе Palm Five Point, Взрывающий Метод Alexandrescu:

template <typename Underlying>
class Transmit
{
public:
   void send(...)
   {
      _U.send(...)
   };

private:
    Underlying _U;
};

class Tcp
{
public:
   void send(...) {};
};

class Udp
{
public:
   void send(...) {};
};

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

Путем код шаблона обычно более эффективен, но также и многое другое.

3
ответ дан 6 December 2019 в 11:53
поделиться

Шаблоны не необходимы (хотя возможное решение). Это - просто внедрение зависимости через шаблоны, а не через конструктора. Лично я сделал бы это через конструктора. Но выполнение его через шаблон приносит Вам сомнительную пользу более дешевого вызова метода (это не должно быть виртуальным). Но также и действительно допускает более легкую компиляторную оптимизацию.

И udp и объекты tcp должны все еще поддерживать тот же интерфейс.
Если Вы делаете это через наследование, они должны оба реализовать единый интерфейс (виртуальный базовый класс), это это сделано через шаблоны, это не необходимо, но компилятор проверит, что они поддерживают те же вызовы метода, которых требует Объект службы.

Как спросили в исходном вопросе, я не вижу явной потребности (или преимущество) для частичной шаблонной специализации (в ситуации, как описано).

Шаблонный метод

class udp {/*Interface Plop*/static void plop(Message&);};
class tcp {/*Interface Plop*/static void plop(Message&);};
template<typename T>
class Service
{
    public:
        void doPlop(Message& m) { T::plop(m);}
    // Do not actually need to store an object if you make the methods static.
    // Alternatively:
    public:
        void doPlop(Message& m) { protocol.plop(m);}
    private:
        T protocol;
};

Полиморфная версия

class Plop{virtual void plop(Message&) = 0;} // Destruct or omitted for brevity
class upd:public Plop {/*Interface Plop*/void plop(Message&);};
class tcp:public Plop {/*Interface Plop*/void plop(Message&);};
class Service
{
    public:
        Service(Plop& p):protocol(p)  {};
        void doPlop(Message& m) { protocol.plop(m);}
    private:
        Plop& protocol;
};
2
ответ дан 6 December 2019 в 11:53
поделиться

Я думаю, что основной момент в выборе среди полиморфизма или обрабатывает специализацию по шаблону, в данном случае по крайней мере, то, если Вы хотите выбрать который поведение использовать во время выполнения или во время компиляции.
Если Вы хотите иметь udp, или базирующееся соединение TCP, например, на строке подключения предоставило пользователю, то полиморфизм лучше всего соответствует Вашим потребностям; создайте реальный класс и затем передайте его общему коду, который обрабатывает указатель на основной интерфейс.
Иначе Вы могли бы рассмотреть использование шаблонов - я не уверен, должны ли Вы обработать специализацию по шаблону.

Надежда это помогает :)

0
ответ дан 6 December 2019 в 11:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: