многопараметрические шаблоны классов и мой класс "вершин" - PullRequest
1 голос
/ 30 мая 2011

Я определил класс «вершина», который при объединении образует граф. эти вершины получают входные данные на одном конце и производят выходные данные на другом (обе эти стороны могут иметь 0, 1 или более «подписок» на другие экземпляры этого класса вершин) Типы как для входящих, так и для исходящих данных не зависят друг от друга и указываются в качестве параметров шаблона, поскольку эти вершины должны работать со всеми видами типов ввода / вывода.

Так в коде это становится:

template<class incomingDataType, class OutgoingDataType>
    class Vertex {...}

Перед отправкой полученных данных, вершина может применить функцию фильтрации для преобразования / фильтрации данных перед отправкой их обратно подписчикам списка. Эта функция объявлена ​​как чисто виртуальная функция, поскольку ее функциональность зависит от вида класса специализации, унаследованного от этого базового класса виртуальной вершины.

Это означает, что фильтр объявлен как:

OutgoingDataType filter(incomingDataType data) = 0; 

Конечно, я хочу связать несколько вершин друг с другом. Рассмотрим эту связь в ее самой простой форме, где вход и выход каждой вершины связан с входом / выходом ровно одной другой вершины:

(ClassX) vertex1 (int) -> (int) vertex2 (std :: string) -> (std :: string) vertex3 (OtherClassOrType) -> ...

Имея это в виду, формулировка проблемы выглядит следующим образом :
vertex2 должен перечислить vertex1 как подписчика и подписаться на vertex3. Чтобы отслеживать все эти подписки, вершина сохраняет набор указателей для всех своих издателей и подписчиков:

template<class incomingDataType, class OutgoingDataType>
class Vertex {
....
bool subscribe(Vertex<OutgoingDataType, __DontCareType__>* subscriber);
OutgoingDataType filter(incomingDataType data) = 0; 
....
//set of 'outgoing vertices' - whom we provide with data
std::set< Vertex<OutgoingDataType, __DontCareType__>* >subscribers_;  
//set of 'incomming vertices' - providing us with data 
std::set< Vertex<__DontCareType__, incomingDataType>* >publishers_; 
}

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

К сожалению, я не могу понять, как я могу это указать. Я уже возился с boost :: any (не компилируется), void указателями (не компилируется), используя шаблоны функций вместо шаблонов классов (не будет работать из-за функции виртуального фильтра) ... но ничего могу думать о делах.

Короче говоря, я ищу способ иметь тип DontCareType в качестве параметра шаблона, если это вообще возможно, что в принципе является способом сказать "параметр шаблона Я отмечаю, что «мне все равно» может быть любого типа, потому что я все равно не использую его данные »

В качестве последнего средства для получения рабочего решения, я также рассматриваю возможность использования своего рода типа «VertexData», который должен быть базовым классом для любых входящих или исходящих типов данных, используемых в вершинах. Это поможет?

Любые другие предложения о том, как сделать это возможным, также приветствуются.

1 Ответ

3 голосов
/ 30 мая 2011

Для этого вы хотите использовать наследование во время выполнения.

template<typename T> struct InputVertex { ... };
template<typename T> struct OutputVertex { ... };
template<typename Incoming, typename Outgoing> struct Vertex 
: public InputVertex<Incoming>, public OutputVertex<Outgoing> {
    std::set<InputVertex<Outgoing>*> outgoings;
public:
    void RegisterFilter(InputVertex<Outgoing>* ptr) {
        outgoings.insert(ptr);
    }
    void RemoveFilter(InputVertex<Outgoing>* ptr) {
        outgoings.erase(ptr);
    }
    void Process(const std::vector<Incoming>& ref) {
        std::vector<Outgoing> output;
        // Transform
        for(auto ref : outgoings) {
            outgoings->Process(output);
        }
    }
};

В этом случае интерфейс для входящего и исходящего трафика четко разделен, что значительно упрощает работу с ними обоими независимо.Извините, что я использую C ++ 0x на основе диапазона для.

...