Usar plantilla actual como parámetro de plantilla para uno de los parámetros de plantilla

8

Estoy tratando de hacer una estructura gráfica genérica, pero me encuentro con esta dependencia circular entre vértices y bordes. Defino mis clases Vertex y Edge así:

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

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

Me gustaría crear una instancia con algo así Vertex<Edge<int, std::shared_ptr<decltype(v)>>> v;, pero obviamente no puedo. ¿Qué puedo hacer para resolver esta dependencia circular?

Editar:

Creo que este problema se reduce a usar la plantilla actual como parámetro de plantilla para uno de los parámetros de plantilla de la plantilla actual, por ejemplo, cómo hacer algo como esto:

template<typename VertexWrapper>
struct Vertex {
    std::vector<pair<int, VertexWrapper<Vertex>>> successors;
};
Simon Berens
fuente
2
template <typename> class VertexWrapper? Además, ¿por qué tiene las etiquetas C ++ 11 y C ++ 17? ¿Qué estándar estás apuntando?
HolyBlackCat
@HolyBlackCat Afaik se aplican, ¿debería usar solo la más reciente? Además, no estoy seguro de qué quieres decir contemplate <typename> typename VertexWrapper
Simon Berens
¿Se VertexWrappersupone que el argumento tipo siempre tiene la forma std::shared_ptr<decltype(v)>o some_template_here<decltype(v)>?
nogal
@walnut debería ser algo así como shared_ptr / unique_ptr / algo con operator->
Simon Berens
Si estoy leyendo esta pregunta correctamente, es posible que desee ver los parámetros de "plantilla de plantilla" stackoverflow.com/questions/213761/…
Joe

Respuestas:

10

Con el parámetro de plantilla de plantilla, puede hacer algo como:

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
fuente
¡Gracias! TIL sobre parámetros de plantilla de plantilla
Simon Berens
2

el suyo simplemente funciona ... (pero no sé cómo imprimir e inicializar el vector miembro)

#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
fuente
1
La idea es tener un Vertex<Edge<double, Vertex</*..*/>>>...
Jarod42
0

La respuesta de Jarod42 funcionará, pero te limita a solo duplicar. Si desea una más flexible que acepte ints, por ejemplo, también tiene esta opción:

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

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

Esto le permitirá usar otros tipos de números, si por alguna razón necesita una abreviatura para eso. Luego, usar dobles se vería así:

myVertex<double> v;
Chipster
fuente
1
Fue solo un ejemplo de uso. Para ir más lejos, lo haríatemplate <typename T> struct graph_type { using egde = Edge<T, Vertex>; using vertex = Vertex<edge>; };
Jarod42