2012-06-19 12 views
6

Info:Rückgabetyp der Template-Funktion

Ich versuche zur Zeit Metaprogrammierung zu lernen (von this book folgenden). Ein nützliches Beispiel, das sie geben, ist für die Dimensionsanalyse. Ich habe es wie im Buch umgesetzt und alles war in Ordnung; see here.

Mein Problem ist jedoch, ich möchte das dimensionale Analyse-Framework mit gemischten Typen verwenden. Damit meinen Sie, dass Sie einen Skalar mit Massenmaßen multiplizieren könnten, der einen Vektor mit Beschleunigungsdimensionen multipliziert, um eine Vektorkraft zu erhalten. Wie es im Link steht, arbeiten sie nur mit dem gleichen Typ T für die Eingabe und Ausgabe aller Operationen.

Ich habe eine 3-Vektorklasse, die durch Skalare zur Multiplikation mit/Dividieren all notwendigen Operationen hat, etc., so würde ich so etwas wie

quantity<double,mass> m(1.0); 
quantity<vect,acceleration> a(vect(0.0,0.0,-9.81)); 
quantity<vect,force> f = m*a; 

Erster Versuch tun:

Um dies zu erreichen, habe ich versucht, die Beispiele aus dem Buch zu erweitern, um zwei verschiedene Typen als Eingaben für operator* und operator/ zu behandeln, jedoch traf ich eine Wand, wenn es um den Rückgabetyp geht.

Ich weiß, hier der Rückgabetyp von double * vectvect ist, aber wenn sie in der anderen Richtung sind um vect * double es ist immer noch ein vect. Schlechter; im Prinzip könnte der Rückgabetyp alles sein. Deshalb möchte ich eine Möglichkeit, die operator* zu so etwas wie

template<class T1, class T2, class Dim1, class Dim2> 
quantity<X, typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type> 
operator*(const quantity<T1,Dim1>& q1, const quantity<T2,Dim2>& q2) 
{ 
    return quantity<X, 
        typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type> 
        (q1.value()*q2.value()); 
} 

auszudehnen, in denen X ist der Rückgabetyp von q1.value()*q2.value() und wird bei der Kompilierung abgeleitet. Ich versuchte, einfach eine weitere Vorlage Klasse T3 zu der Signatur hinzufügen und es T3 zurückgeben, aber es scheint, es kann nicht ableiten, was T3 sollte sein.

Zweiter Versuch:

Weiter habe ich versucht, mit decltype wie

folgt
template<class T1, class T2> 
struct return_type 
{ 
    auto mult_f(const T1& a, const T2& b)->decltype(a*b){return a*b;} 
    typedef decltype(mult_f) type; 
}; 

template<class T1, class T2, class Dim1, class Dim2> 
quantity<typename return_type<T1,T2>::type, typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type> 
operator*(const quantity<T1,Dim1>& q1, const quantity<T2,Dim2>& q2) 
{ 
    return quantity<typename return_type<T1,T2>::type, 
        typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type> 
        (q1.value()*q2.value()); 
} 

Doch diese eine Vielzahl von unverständlichen Compiler-Fehler führt.

Frage:

Meine Frage ist, dann bin ich decltype in der richtigen Art und Weise verwenden, aber fehlen einige Syntax z.B. ein typename Spezifizierer irgendwo? Oder; Ist das überhaupt möglich und wenn nicht, wie ist es möglich, den Rückgabetyp einer Funktion zu berechnen?

Danke.

Antwort

6

Ok, also zuerst der Typ return_type<T1,T2>::type ist nicht, was Sie zu erwarten scheinen, aber ist der Typ einer Methode, nämlich T3 (return_type::*)(const T1&, const T2&) mit T3 ist der Typ, den Sie erwarten.Wenn Sie eine Zwischenklasse verwenden möchten, können Sie:

template <typename T1, typename T2> 
struct return_type 
{ 
    typedef decltype(std::declval<T1>()*std::declval<T2>()) type; 
}; 

Aber man könnte auch direkt decltype(T1()*T2()) verwenden, um die Art des Produkts zu erhalten.

Bearbeiten: Ich habe den Code mit dem Vorschlag von ildjarn bearbeitet, so dass keine standardkonstruierbaren Typen erforderlich sind. Nur nicht vergessen, <utility>

+0

Yeah, ich konnte aus der Compiler-Ausgabe, dass ich die ganze Funktion Signatur bekam sagen. Ich weiß nicht, warum ich die Dinge so kompliziert gemacht habe, dein Beispiel kompiliert gut :) Die Standard-Konstruktor-Anforderung ist für mich kein Problem. – Dan

+2

@Dan: Beachten Sie, dass das Buch vor C++ 11 und 'declype' /' auto' Verfügbarkeit geschrieben wurde, was die Dinge ** viel ** komplizierter gemacht hat. –

+2

Ersetzen Sie 'declltype (T1() * T2())' mit 'declltype (std :: declval () * std :: declval ())' und Sie benötigen keine Standard-Constructibility mehr. – ildjarn

Verwandte Themen