Как я могу извлечь из шаблона дважды, и чтобы подклассы взаимодействовали? - PullRequest
2 голосов
/ 07 мая 2011

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

Вот шаблон, и у меня есть класс Wire, производный от TwoTypeMesh<Wire, CircuitComponent> и класс CircuitComponent, производный от TwoTypeMesh<CircuitComponent, Wire>:

template <class thisType, class otherType>
class TwoTypeMesh {
    std::set<otherType *> neighbors;
public:
    void join(otherType * n){
        if (neighbors.find(n) != neighbors.end()) {
            return;
        } else {
            neighbors.insert(n);
            n->join(this);
        }
    }

    void disconnect(otherType * n){
        if (neighbors.find(n) == neighbors.end()) {
            return;
        } else {
            neighbors.erase(n);
            n->disconnect(this);
        }
    }
};

Проблема в том, что я не могу заставить его скомпилировать, он жалуется на строку с n->join(this) причина this имеет тип TwoTypeMesh<Wire, CircuitComponent> (суперкласс Wire), но join определен только для wire.

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

Ответы [ 3 ]

1 голос
/ 07 мая 2011

Минимально инвазивный способ заставить ваш код компилироваться - это действительно использовать typedef и либо теги классов , либо просто перечисления:

enum MeshType { MeshTypeWire, MeshTypeCircuitComponent };

template <MeshType thisType>
class TwoTypeMesh {
    // calculate 'otherType' from 'thisType' (prevents usage mistakes):
    static const MeshType otherType =
        thisType == MeshTypeWire ? MeshTypeCircuitComponent :
        /* else */                 MeshTypeWire ;
    std::set< TypeTwoMesh<otherType> *> neighbors;
public:
    void join(TypeTwoMesh<otherType> * n){
        if (neighbors.find(n) != neighbors.end()) {
            return;
        } else {
            neighbors.insert(n);
            n->join(this);
        }
    }

    void disconnect(TypeTwoMesh<otherType> * n){
        if (neighbors.find(n) == neighbors.end()) {
            return;
        } else {
            neighbors.erase(n);
            n->disconnect(this);
        }
    }
};

typedef TwoTypeMesh<MeshTypeWire> Wire;
typedef TwoTypeMesh<CircuitComponent> CircuitComponent;
1 голос
/ 07 мая 2011

переместите join () за пределы класса:

void join(Wire &w, CircuitComponent &j);
void join(CircuitComponent &j, Wire &w);

, возможно, вам понадобится сделать функции друзьями класса для доступа к частным элементам данных.

0 голосов
/ 08 мая 2011

Чтобы устранить вашу конкретную ошибку компиляции, вы должны быть в состоянии static_cast this до thisType* при вызове n->join.

Похоже, вы случайно заново изобрели CRTP : базовый класс шаблона, который принимает производный класс в качестве параметра шаблона.Просто никогда не наследуйте от TwoTypeMesh<T,U> ни в каком классе, кроме T, и сделайте конструкторы TwoTypeMesh защищенными для предотвращения прямой реализации.Тогда вы можете быть уверены, что любой экземпляр TwoTypeMesh<T, something> является подобъектом базового класса экземпляра T (или производного класса T), и, следовательно, допустимы значения от static_cast до T*.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...