6 Stimmen

Unterstützt C++ einzelne generische Methoden anstelle von generischen Klassen?

Das ist wichtig: Diese Frage wird ziemlich lang, wenn dies das erste Mal, dass Sie dies lesen, schlage ich vor, Sie beginnen in der Nähe der Unterseite als die Lösung ist es in einer Runde über Weg, aber der Code ist ein bisschen stinkend.

Nach der Lektüre eines Tutorial zu Vorlagen konnte ich meine bestehende Klasse so ändern, dass sie generische Typen unterstützt. Allerdings sind viele Objekte bereits davon abhängig, also suche ich nach einer Möglichkeit, eine Methode generisch zu machen, anstatt die gesamte Klasse.

Ich habe Folgendes versucht, aber es sieht so aus, als ob dieses Verhalten nicht unterstützt wird.

// foobar1.h
// Don't want the entire class to be generic.
//template<class T>
class FooBar1
{
public:
    template<class T> T Foo();
}

// foobar2.h
class FooBar2 : public FooBar1
{
}

// foobar1.cpp
template<class T>
T FooBar1::Foo()
{
    return something;
}

// test.cpp
FooBar1 fb1;
FooBar2 fb2 = fb1.Foo<FooBar2>();

Soll das nicht funktionieren, oder ist es ein Fehler, der mich verwirrt?

undefinierter Verweis auf FooBar2 Foo<FooBar2>()

Um dies in eine Art von Perspektive zu setzen, was ich erreichen möchte, hier ist, wie ich es in C# tun würde ...

public class FooBar1
{
    public T Foo<T>()
        where T : FooBar1
    {
        return something;
    }
}

public class FooBar2 : FooBar1 { }

FooBar1 fb1 = new FooBar1();
FooBar2 fb2 = fb1.Foo<FooBar2>();

Gibt es eine Möglichkeit, etwas Ähnliches in C++ zu tun?

Aktualisierung 1:

Ich habe nur einige kleinere Syntaxdetails korrigiert (ich wollte Foo öffentlich machen und T zurückgeben, nicht FooBar2). Immer noch Compiler-Fehler... Wenn ich die Vorlage Verhalten der Fehler geht weg, die Antwort so weit sagen, was ich tue, ist gültig... aber wenn es dann ist, warum ich den Fehler immer noch bekommen? Vielen Dank für Ihre Antworten!

Update 2:

Josh, hier ist der eigentliche Quellcode (also das, was ich für relevant halte - lassen Sie es mich wissen, wenn Sie denken, dass ich einen wichtigen Teil übersprungen habe).

// ImageMatrix.h
class ImageMatrix : public VImage
{
public:
    // ... various functions ...
    template<class T> T GetRotatedCopy(VDouble angle);
}

// ImageFilter.h
class ImageFilter : public ImageMatrix
{
    // ... various functions ...
}

// ImageMatrix.cpp
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
    // ... create a new instance of ImageMatrix and return it.
}

// ImageProcessor.cpp
ImageFilter filter2 = filterPrototype.GetRotatedCopy<ImageFilter>(90);

Und hier ist der eigentliche Compiler-Fehler:

/home/nick/Projects/ViMRID/vimrid/Debug/libvimrid.so: undefinierte Referenz auf `vimrid::imaging::processing::ImageFilter vimrid::imaging::ImageMatrix::GetRotatedCopy(double)'

Aktualisierung 3:

Übrigens, alles außer der Implementierungszeile befindet sich in einer Bibliothek; es wird also von einer separaten Binärdatei aufgerufen... Ist das von Bedeutung? Berichtigung: Alle Blöcke befinden sich in derselben Bibliothek. Alle Blöcke sind jedoch unterschiedliche Dateien.

Update 4:

Wenn ich die Implementierung Zeile auskommentieren (ImageFilter filter2 = filterPrototype...) es baut gut, so scheint es diese Zeile zu sein, die es verursacht...

Update 5 (Gelöst?):

Ich habe immer noch Probleme... Könnte dies ein Problem mit den Namensräumen sein? Streichen Sie das, OK, jetzt habe ich das Konzept der Vorlagen begriffen! :) Die Vorlagendefinition muss zusammen mit der Deklaration in der Kopfzeile stehen (richtig?) - nachdem ich also die Deklaration in den Bereich ImageMatrix.h kompiliert alles. Allerdings musste ich mit dynamic_cast um es zum Laufen zu bringen; ist das richtig? Wenn ich falsch liege, korrigieren Sie mich bitte!

// This is in the header file!
// Help!!! This looks really really smelly...
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
    ImageMatrix image = _getRotatedCopy(angle);
    ImageMatrix *imagePtr = &image;
    return *dynamic_cast<T*>(imagePtr);
}

Update 6:

Bezogen auf Update 5, wenn ich dynamic_cast nicht verwende...

template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
    ImageMatrix image = _getRotatedCopy(angle);
    ImageMatrix *imagePtr = &image;
    //return *dynamic_cast<T*>(imagePtr);
    return *imagePtr;
}

... Ich erhalte diesen Fehler ...

../src/imaging/processing/../ImageMatrix.h: In member function ‘T vimrid::imaging::ImageMatrix::GetRotatedCopy(vimrid::VDouble) [with T = vimrid::imaging::processing::ImageFilter]’:
../src/imaging/processing/ImageProcessor.cpp:32:   instantiated from here
../src/imaging/processing/../ImageMatrix.h:45: error: conversion from ‘vimrid::imaging::ImageMatrix’ to non-scalar type ‘vimrid::imaging::processing::ImageFilter’ requested
make: *** [src/imaging/processing/ImageProcessor.o] Error 1

Update 7:

Und wenn ich den ganzen stinkenden Code in Update 6 nicht verwende...

class ImageMatrix : public VImage
{
public:
    template<class T> T GetRotatedCopy(VDouble angle);
private:
    ImageMatrix _getRotatedCopy(VDouble angle);
};

template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
    return _getRotatedCopy(angle);
}

... Ich erhalte den gleichen Fehler wie bei Update 6.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X