2016-04-14 8 views
2

Wie kann ich Code zwischen einer spezialisierten und nicht spezialisierten Version einer C++ - Klasse freigeben?Freigeben von Code zwischen einer spezialisierten und nicht spezialisierten Templatestruktur

Hier ist ein konstruiertes Beispiel dafür, was ich versuche zu erreichen:

mit zur Verbindungszeit
#include <iostream> 
using namespace std; 

template <size_t n> struct Y { 
    int one() { return 1; } 
    int two(); 
}; 

template <> struct Y<1> { 
    int one() { return 11; } 
    int two(); 
}; 

template <size_t n> int Y<n>::two() { return one() * 2; } 

int main() { 
    Y<1> X; 
    cout << X.one(); 
    cout << X.two(); 
    return 0; 
} 

Dies schlägt fehl:

Undefined symbols for architecture x86_64: 
    "Y<1ul>::two()", referenced from: 
     _main in test-7c4ebe.o 

Allerdings, wenn ich die Y<1> X;-Y<2> X; ändern, Kompilierung erfolgreich Alles gut.

Mein Ziel hier war die Verwendung der Beispielimplementierung von two() für die spezialisierte und unspezialisierte Version der Klasse.

konnte ich wie so um dieses Problem mit Vererbung erhalten:

#include <iostream> 
using namespace std; 

struct mixin { 
    virtual int one() = 0; 
    int two() { return one() * 2; } 
}; 

template <size_t n> struct Y : public mixin { 
    int one() { return 1; } 
}; 

template <> struct Y<1> : public mixin { 
    int one() { return 11; } 
}; 

int main() { 
    Y<1> X; 
    cout << X.one(); 
    cout << X.two(); 
    return 0; 
} 

Aber ich denke, dass bei jedem Aufruf von Y<n>.two(), rechts eine unnötigen v-Lookup-Tabelle verursacht?

Gibt es eine Möglichkeit, Code zwischen der spezialisierten und unspezialisierten Version freizugeben, ohne die Vererbung zu missbrauchen und einen V-Table-Lookup-Aufruf auszuführen?

+0

define * missbrauchen * in Erbschaft. – SergeyA

+0

@SergeyA scheint mir, dass diese Vielzahl von Problemen lösbar sein sollte, ohne Vererbung zu verwenden, obwohl, wenn es eine Lösung gibt, die Vererbung verwendet, aber eine V-Tabellen-Suche vermeidet, das in Ordnung wäre. –

+0

@SergeyA: OK, ich missverstanden. – AnT

Antwort

2

Sie müssen one Methode zu mixin überhaupt nicht hinzufügen. Haben Sie einfach mixin mit einer nicht-virtuellen two Methode, um seine Implementierung mit der abgeleiteten Klasse Y zu teilen und CRTP zu verwenden.

#include <iostream> 
using namespace std; 

template <class Derive> 
struct mixin { 
    int two() { return ((Derive *)this)->one() * 2; } 
}; 

template <size_t n> struct Y : public mixin <Y<n>> { 
    int one() { return 1; } 
}; 

template <> struct Y<1> : public mixin <Y<1>> { 
    int one() { return 11; } 
}; 

int main() { 
    Y<1> X; 
    cout << X.one(); 
    cout << X.two(); 
    return 0; 
} 
2

Sie können die eine Methode speciliaze anstelle der Klasse Spezialisierung:

template <size_t n> struct Y { 
    int one() { return 1; } 
    int two() { return one() * 2; } 
    int theird(); // declare only for Y<N> 
}; 

template <> 
int Y<1>::one() { return 11; } 

// only for Y<1> 
template <> 
int Y<1>::theird() { return one()*two();} 
+0

Ah, ja. Dies würde in diesem Szenario funktionieren, aber ich möchte Methoden für 'Y <1>' definiert haben, die überhaupt nicht auf' Y 'existieren. –

+1

Sie können es tun, wenn Sie nur solche Methoden deklarieren und sie nur für das Y <1> spezialisieren. – AnatolyS

+0

Nur um Ihren Kommentar zu verdeutlichen, meinen Sie, ich könnte die Methode definieren, die ich nur für Y <1> auf der Definition von Y existieren möchte, aber dann implementieren Sie es nur spezialisiert für Y <1>? –

1

Statt CRTP, können Sie es auch tun andersrum:

#include <iostream> 
using namespace std; 

template <size_t n> struct Y { 
    int one() { return 1; } 
}; 

template <> struct Y<1> { 
    int one() { return 11; } 
}; 

template <size_t n> 
struct mixin : Y<n> { 
    int two() { return Y<n>::one() * 2; } 
}; 

int main() { 
    mixin<1> X; 
    cout << X.one(); 
    cout << X.two(); 
    return 0; 
} 

Oder alternativ :

template <class P> 
struct mixin : P { 
    int two() { return P::one() * 2; } 
}; 

mixin<Y<1>> X; 
Verwandte Themen