Frage

Diese Frage bezieht sich auf meine letzte ein . Ich versuche, das Problem mit traits<T> und traits<T*> zu lösen. Bitte beachten Sie den folgenden Code ein.

template<typename T>
struct traits
{
    typedef const T& const_reference;
};

template<typename T>
struct traits<T*>
{
    typedef const T const_reference;
};

template<typename T>
class test
{
public:   
    typedef typename traits<T>::const_reference const_reference;
    test() {}   
    const_reference value() const {
        return f;
    }
private:
    T f;
};

int main()
{
    const test<foo*> t;
    const foo* f = t.value(); // error here. cannot convert ‘const foo’ to ‘const foo*’ in initialization
    return 0;
}

So sieht es aus wie Compiler nicht die Züge Spezialisierung für Zeiger unter Berücksichtigung und Rückgabetyp value() als const foo nehmen statt const foo*. Was mache ich falsch hier?

Jede Hilfe wäre toll!

War es hilfreich?

Lösung

Die Spezialisierung verwendet wird. traits<foo*>::const_reference ist const foo. Wenn Sie wollen, dass es ein Zeiger sein, zu verwenden:

template<typename T>
struct traits<T*>
{
    typedef const T* const_reference;
};

Damit wird traits<foo*>::const_reference const foo* sein.

Beachten Sie, dass die Verwendung von T in der traits<T*> Spezialisierung aus dem T in der traits Vorlage vollständig getrennt ist. Man könnte es umbenennen:

template<typename U>
struct traits<U*>
{
    typedef const U* const_reference;
};

und Sie haben die gleiche Spezialisierung haben. Es macht mehr Sinn, wenn Sie Erfahrung in der funktionalen Programmierung haben.

Um zu beginnen, denken Sie an der template <typename ...> als eine Abstraktion der Einführung, eher wie eine Funktion Abstracts aus einem Wert. Es ist wie das Drehen

sum = 0
for item in [1,2,3]:
    sum += item

in:

function sum(l):
    sum = 0
    for item in l:
        sum += item
    return sum

wo l an die Stelle der [1,2,3] nimmt. Wir können sums von einer anderen Funktion aufrufen, die selbst einen formalen Parameter namens l hat:

function sumsq(l):
    return sum(map(lambda x: x*x, l))

sumsq der "l" hat nichts mit sum des "l" zu tun.

Mit Vorlagen, wir abstrakte Typnamen anstatt Werte. Das heißt, wir drehen:

struct traits {
    typedef const double& const_reference;
};

in:

template <typename T>
struct traits {
    typedef const T& const_reference;
};

Betrachten wir nun eine Nicht-Template-Spezialisierung:

template <>
struct traits<double*> {
    typedef const double* const_reference;
};

Hier gibt es keine Template-Parameter für die Spezialisierung, aber Sie können von traits<double*> denken als eine traits Vorlage auf ein double* Anwendung. Auszug aus dem double und Sie haben:

template <typename T>
struct traits<T*> {
    typedef const T* const_reference;
};

Hier ist der T ist ein Parameter für die Spezialisierung, nicht die Basisvorlage.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top