Explicit template instantiation
-
Hallo,
Ich arbeite auf einem Mac OS 10.5 (g++: i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 )und versuche folgendes Programm zu kompilieren:
http://www.csd.uwo.ca/faculty/yuri/Implementations/maxflow-v3.0.src.tar.gz
(mit dem main.cpp aus dem README.TXT File)Allerdings erhalte ich folgenden Fehler:
make all Building file: ../graph.cpp Invoking: GCC C++ Compiler g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"graph.d" -MT"graph.d" -o"graph.o" "../graph.cpp" Finished building: ../graph.cpp Building file: ../maxflow.cpp Invoking: GCC C++ Compiler g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"maxflow.d" -MT"maxflow.d" -o"maxflow.o" "../maxflow.cpp" Finished building: ../maxflow.cpp Building target: Maxflow Invoking: MacOS X C++ Linker g++ -o "Maxflow" ./graph.o ./main.o ./maxflow.o ld: duplicate symbol Graph<int, int, int>::add_node(int)in ./maxflow.o and ./graph.o collect2: ld returned 1 exit status make: *** [Maxflow] Error 1Was mach ich falsch? Sollte doch klappen so, oder?
-
Ich glaube ich konnte den Fehler inzwischen etwas eingrenzen.
Main sieht folgendermassen aus:
#include <stdio.h> #include "graph.h" int main() { extern typedef Graph<int,int,int> GraphType; GraphType *g = new GraphType(/*estimated # of nodes*/ 2, /*estimated # of edges*/ 1); // g->add_node(); g->add_node(); // g->add_tweights( 0, /* capacities */ 1, 5 ); g->add_tweights( 1, /* capacities */ 2, 6 ); g->add_edge( 0, 1, /* capacities */ 3, 4 ); int flow = g->maxflow(); // int flow = 3; printf("Flow = %d\n", flow); printf("Minimum cut:\n"); if (g->what_segment(0) == GraphType::SOURCE) printf("node0 is in the SOURCE set\n"); else printf("node0 is in the SINK set\n"); if (g->what_segment(1) == GraphType::SOURCE) printf("node1 is in the SOURCE set\n"); else printf("node1 is in the SINK set\n"); delete g; return 0; }und die graph.h
template <typename captype, typename tcaptype, typename flowtype> class Graph { public: typedef enum { SOURCE = 0, SINK = 1 } termtype; // terminals typedef int node_id; Graph(int node_num_max, int edge_num_max, void (*err_function)(char *) = NULL); ~Graph(); node_id add_node(int num = 1); void add_edge(node_id i, node_id j, captype cap, captype rev_cap); void add_tweights(node_id i, tcaptype cap_source, tcaptype cap_sink); flowtype maxflow(bool reuse_trees = false, Block<node_id>* changed_list = NULL); termtype what_segment(node_id i, termtype default_segm = SOURCE); private: struct node; struct arc; };(Graph.h ist noch länger, aber ich denke das ist das wichtigste )
Das Problem liegt nun beim Aufruf von
int flow = g->maxflow();in Zeile 16 vom Main. Ich erhalte den Fehler:
Undefined symbols: "Graph<int, int, int>::maxflow(bool, Block<int>*)", referenced from: _main in main.oGemäss diesem Ratschlag: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13 versuchte ich schliesslich eine Instanz im Main zu erzeugen und fügte die Zeile
template int Graph<int,int,int>::maxflow(bool,Block<int>*);am Ende des main.cpp Files ein.
Dies ergibt allerdings folgenden Error:
../main.cpp: In instantiation of 'flowtype Graph<captype, tcaptype, flowtype>::maxflow(bool, Block<int>*) [with captype = int, tcaptype = int, flowtype = int]': ../main.cpp:23: instantiated from here ../main.cpp:23: error: explicit instantiation of 'flowtype Graph<captype, tcaptype, flowtype>::maxflow(bool, Block<int>*) [with captype = int, tcaptype = int, flowtype = int]' but no definition availableSo wie ich das verstehe liegt das Problem dass ich beim Instanzieren der maxflow Funktion den Rückgabewert int angegeben habe. Dieser ist im template allerdings als flowtype deklariert. Hier ist er aber int.
Irgendwie steh ich auf dem Schlauch. Habt ihr Ideen wie ich das ganze zum laufen bringen kann? ( Wenn ich als Rückgabewert flowtype angebe klappts auch nicht:
../main.cpp:42: error: ISO C++ forbids declaration of 'flowtype' with no type ../main.cpp:42: error: explicit instantiation of non-template 'int flowtype' ../main.cpp:42: error: expected `;' before 'Graph')
-
Nachtrag:
In der oben aufgezeigten Version habe ich die #include "instances.inc"
in graph.cpp und maxflow.cpp der Originalversion ( -> http://www.csd.uwo.ca/faculty/yuri/Implementations/maxflow-v3.0.src.tar.gz ) entfernt ( Errorld: duplicate symbol Graph<int, int, int>::add_node(int)in ./maxflow.o and ./graph.o)und stattdessen
template class Graph<int,int,int>; template class Graph<short,int,int>; template class Graph<float,float,float>; template class Graph<double,double,double>;am Ende vom graph.cpp File eingefügt.
-
Wie sieht denn flowtype aus? - Und klappt es, wenn du da wirklich den Rückgabewert int machst? (also den halt auch mal eben in der Klasse anpasst)
-
Nein, leider nicht. Habe es soeben versucht und der Fehler bleibt der Gleiche:
../main.cpp: In instantiation of 'int Graph<captype, tcaptype, flowtype>::maxflow(bool, Block<int>*) [with captype = int, tcaptype = int, flowtype = int]': ../main.cpp:23: instantiated from here ../main.cpp:23: error: explicit instantiation of 'int Graph<captype, tcaptype, flowtype>::maxflow(bool, Block<int>*) [with captype = int, tcaptype = int, flowtype = int]' but no definition availableworan kann das denn nur liegen?
-
drakon schrieb:
Wie sieht denn flowtype aus?
Der flowtype wird dem Graph beim instanzieren übergeben:
template <typename captype, typename tcaptype, typename flowtype> Graph<captype, tcaptype, flowtype>::Graph(int node_num_max, int edge_num_max, void (*err_function)(char *)) { // graph }