Template Funktion



  • Hallo!

    Ich war gerade kurz davor 3 Funktionen zu implementieren, die alle das gleiche machen, bis auf dass bei dem Teil, an dem eine neue Instanz einer Templateklasse erzeugt eine 1,2 oder 3 übergebeben wird. Da kam mir die glorreiche Idee daraus ebenfalls ein Template zu machen:

    template<unsigned int DIM>
    void vtk2itk(vtkImageData* vtkOutImage)
    {    
        const char* scalarTypeString = vtkOutImage->GetScalarTypeAsString();
        if (strcmp("VTK_CHAR", scalarTypeString) == 0) {
    	typedef char scalarType;
    	typedef itk::Image<scalarType, DIM>	InputType;
    	typedef itk::VTKImageImport<InputType> 	ImageImportType;
    	ImageImportType::Pointer itkImporter;
    	itkImporter = ImageImportType::New();
    	connectITKImporter(itkImporter, vtkOutImage);
        } else if (strcmp("VTK_UNSIGNED_CHAR", scalarTypeString) == 0) {
    	typedef unsigned char scalarType;
            ...
    }
    

    Leider kommt hier die wirklich merkwürdige Fehlermeldung:

    /home/christian/programming/pv-plugins/vtk2itk2vtk/vtk2itk2vtk.cxx: In function 'void vtk2itk(vtkImageData*)':
    /home/christian/programming/pv-plugins/vtk2itk2vtk/vtk2itk2vtk.cxx:9: error: expected `;' before 'itkImporter'                                                                                                            
    /home/christian/programming/pv-plugins/vtk2itk2vtk/vtk2itk2vtk.cxx:10: error: 'itkImporter' was not declared in this scope
    

    Sehr merkwürdig deswegen, weil alles problemlos kompiliert, wenn ich die Template Deklaration weglasse und das ganze so schreibe:

    void vtk2itk(vtkImageData* vtkOutImage)
    {    
        #define DIM 3
        const char* scalarTypeString = vtkOutImage->GetScalarTypeAsString();
        if (strcmp("VTK_CHAR", scalarTypeString) == 0) {
    	typedef char scalarType;
    	typedef itk::Image<scalarType, DIM>	InputType;
    	typedef itk::VTKImageImport<InputType> 	ImageImportType;
    	ImageImportType::Pointer itkImporter;
    	itkImporter = ImageImportType::New();
    

    Ich muss zugeben, das ist das erste Mal, dass ich mich an sowas versuche. Aber nachdem ich mich nun stundenlang nach Beispielen umgesehen und mir 3 Mal das Kapitel über Templates in meinem O'Reilly durchgelesen haben (nirgends finde ich übrigens so ein "einfaches" Template, wo nur ein int übergeben wird), weiß ich nicht mehr weiter...

    Hat jemand einen guten Rat?

    Viele Grüße,
    Christian



  • Das übliche Problem, dass der Typ ImageImportType::Pointer von einem Template-Parameter abhängt und deshalb vom Compiler nicht als Typ erkannt werden kann. typename ImageImportType::Pointer sollte das Problem lösen.



  • Danke für die schnelle Antwort! Das freut mich, dass es ein Standardproblem ist, aber wo soll ich genau dieses "typename ..." hinschreiben? In die Templatedefinition oder mitten in den Code?

    typename ImageImportType::Pointer;
    

    Am Anfang der Funktion ist jedenfalls schonmal falsch:

    error: declaration does not declare anything
    


  • Siehe http://www.c-plusplus.net/forum/viewtopic-var-t-is-261050-and-highlight-is-*typename*.html

    Also ja, mitten in den Code:

    typedef itk::Image<scalarType, DIM>    InputType;
        typedef itk::VTKImageImport<InputType>     ImageImportType;
        typename ImageImportType::Pointer itkImporter;
    


  • Oh, hrrhrr... :p Hatte ich schon gemacht, aber halt nur an einer Stelle eingefügt, hinter dem ... kommt das ganze ja noch 10 Mal, also hat er sich dann immernoch 9 Mal beschwert.

    Apropos, meine Funktion sieht jetzt so aus:

    const char* scalarTypeString = vtkOutImage->GetScalarTypeAsString();
    
        if (strcmp("VTK_CHAR", scalarTypeString) == 0) {
    	typedef char scalarType;
    	typedef itk::Image<scalarType, DIM>	InputType;
    	typedef itk::VTKImageImport<InputType> 	ImageImportType;
    	typename ImageImportType::Pointer itkImporter;
    	itkImporter = ImageImportType::New();
    	connectITKImporter(itkImporter, vtkOutImage);
    
        } else if (strcmp("VTK_UNSIGNED_CHAR", scalarTypeString) == 0) {
    	typedef unsigned char scalarType;
    	typedef itk::Image<scalarType, DIM>	InputType;
    	typedef itk::VTKImageImport<InputType> 	ImageImportType;
    	typename ImageImportType::Pointer itkImporter;
    	itkImporter = ImageImportType::New();
    	connectITKImporter(itkImporter, vtkOutImage);
    ...und das alles für jeden Datentyp...
    

    Das kann ich nicht zufällig abkürzen oder? Ich mach ja ne Fallunterscheidung und erst dann den typedef, also ist dieser ja nur in der If-Umgebung gültig. Das ganze itkImport = new... am Schluß, nach den ganzen IFs geht nicht, da meckert er natürlich, dass er den Typ nicht kennt...

    Ist aber nicht so wichtig, es läuft ja. Vielen Dank für die schnelle Antwort.

    Super Forum hier, bin (mal wieder) begeistert! 👍



  • Vielleicht so (ungetestet)?

    struct TypeSelectBase
    {
    	virtual void callConnect(int dim, vtkImageData* vtkOutImage) = 0;
    };
    
    template<typename T>
    struct TypeSelect : public TypeSelectBase
    {
    	virtual void callConnect(int dim, vtkImageData* vtkOutImage)
    	{
    		typedef T scalarType;
    		typedef itk::Image<scalarType, DIM>    InputType;
    		typedef itk::VTKImageImport<InputType>     ImageImportType;
    		typename ImageImportType::Pointer itkImporter;
    		itkImporter = ImageImportType::New();
    		connectITKImporter(itkImporter, vtkOutImage); 
    	}
    };
    
    template<unsigned int DIM>
    void vtk2itk(vtkImageData* vtkOutImage)
    {
    	TypeSelectBase* pointer;
        const char* scalarTypeString = vtkOutImage->GetScalarTypeAsString();
        if (strcmp("VTK_CHAR", scalarTypeString) == 0) {
    		pointer = new TypeSelect<char>;
        } else if (strcmp("VTK_UNSIGNED_CHAR", scalarTypeString) == 0) {
    		pointer = new TypeSelect<unsigned char>;
    	}
    	...
    	pointer->callConnect(DIM, vtkOutImage);
    	delete pointer;
    }
    

    Edit: Moment, das kann so noch nicht klappen.
    Edit: Doch, es müsste so klappen.



  • Danke, funktioniert alles bestens. Jetzt kann ich auch endlich vernünftig mit Templates umgehen! 🕶


Anmelden zum Antworten