Verwenden Sie die aktuelle Vorlage als Vorlagenparameter für einen der Vorlagenparameter

8

Ich versuche, eine generische Diagrammstruktur zu erstellen, aber ich stoße auf diese kreisförmige Abhängigkeit zwischen Scheitelpunkten und Kanten. Ich definiere meine Vertex- und Edge-Klassen folgendermaßen:

template<typename EdgeType>
struct Vertex {
    std::vector<EdgeType> successors;
};

template<typename EdgeCostType, typename VertexWrapper>
struct Edge {
    EdgeCostType cost;
    VertexWrapper source;
    VertexWrapper dest;
};

Ich würde es gerne mit so etwas instanziieren Vertex<Edge<int, std::shared_ptr<decltype(v)>>> v;, aber ich kann es offensichtlich nicht. Was kann ich tun, um diese zirkuläre Abhängigkeit aufzulösen?

Bearbeiten:

Ich denke, dieses Problem besteht darin, die aktuelle Vorlage als Vorlagenparameter für einen der Vorlagenparameter der aktuellen Vorlage zu verwenden, z. B. wie man so etwas macht:

template<typename VertexWrapper>
struct Vertex {
    std::vector<pair<int, VertexWrapper<Vertex>>> successors;
};
Simon Berens
quelle
2
template <typename> class VertexWrapper? Warum haben Sie sowohl C ++ 11- als auch C ++ 17-Tags? Auf welchen Standard zielen Sie ab?
HolyBlackCat
@HolyBlackCat Afaik beide gelten, sollte ich nur die neueste verwenden? Ich bin mir auch nicht sicher, was du damit meinsttemplate <typename> typename VertexWrapper
Simon Berens
Soll das VertexWrapperTypargument immer die Form haben std::shared_ptr<decltype(v)>oder some_template_here<decltype(v)>?
Walnuss
@walnut sollte es so etwas wie shared_ptr / unique_ptr / etwas mit operator-> sein
Simon Berens
Wenn ich diese Frage richtig lese, sollten Sie sich die Parameter "Vorlagenvorlage" ansehen. Stackoverflow.com/questions/213761/…
Joe

Antworten:

10

Mit dem Vorlagenvorlagenparameter können Sie Folgendes tun:

template<typename EdgeType>
struct Vertex {
    std::vector<EdgeType> successors;
};

template<typename EdgeCostType, template <typename> class VertexWrapper>
struct Edge {
    EdgeCostType cost;
    VertexWrapper<Edge> source;
    VertexWrapper<Edge> dest;
};


using myEdge = Edge<double, Vertex>;
using myVertex = Vertex<myEdge>;
Jarod42
quelle
Vielen Dank! Bis zu Vorlagenvorlagenparametern
Simon Berens
2

deins funktioniert einfach .. (aber ich weiß nicht, wie man einen Mitgliedsvektor druckt und initialisiert)

#include <vector>
#include <iostream>  
using namespace std;

template<typename EdgeType>
struct Vertex {
    vector<EdgeType> successors;
};

template<typename EdgeCostType, typename VertexWrapper>
struct Edge {
    EdgeCostType cost;
    VertexWrapper source;
    VertexWrapper dest;
};

int main (){

    Vertex<int> vertx = {{5}};
    Edge<int, decltype(vertx)> ed = {7};

    cout<< ed.cost <<"\n";     //cout<< ed.dest.successors<<"\n";   // not work, ask help!
}
nonock
quelle
1
Die Idee ist, einen Vertex<Edge<double, Vertex</*..*/>>>...
Jarod42
0

Die Antwort von Jarod42 wird funktionieren, aber Sie müssen nur verdoppeln. Wenn Sie eine flexiblere Version wünschen, die beispielsweise ints akzeptiert , haben Sie auch folgende Option:

template<class T>
using myEdge = Edge<T, Vertex>;

template<class T>
using myVertex = Vertex<myEdge<T>>;

Auf diese Weise können Sie andere Arten von Zahlen verwenden, wenn Sie aus irgendeinem Grund eine Abkürzung dafür benötigen. Dann würde die Verwendung von Doppel wie folgt aussehen:

myVertex<double> v;
Chipster
quelle
1
Es war nur eine beispielhafte Verwendung. Um weiter zu gehen, würde ich tuntemplate <typename T> struct graph_type { using egde = Edge<T, Vertex>; using vertex = Vertex<edge>; };
Jarod42