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 1
    

    Was 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.o
    

    Gemä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 available
    

    So 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 ( Error

    ld: 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 available
    

    woran 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
    
    }
    

Anmelden zum Antworten