2017-10-05 1 views
1

Ich denke, ich vermisse nur etwas Kleines. Ich möchte den Konstruktor einer Vorlagenklasse für eine Implementierung spezialisieren, wobei T = die Vorlagenklasse mit einem beliebigen Parameter ist. Entschuldigung, wenn mein Vokabular ein bisschen aus ist. Grundsätzlich muss ich für gezackten 2D-Arrays ermöglichen, so dass ich vielleicht eine ArEl<ArEl<int>> haben, und ich möchte alle Array-Längen preinitialise.Wie implementiere ich die Vererbung in einer partiellen Klassenvorlagenspezialisierung?

using namespace std; 

template <typename T> 
class ArEl { 
public: 
    ArEl(size_t size = 0) 
     : rSize(size), rArray(rSize ? new T[rSize]() : nullptr) {} 
    ArEl(const ArEl& other); 
    virtual ~ArEl() { delete[] rArray; } 
    void swap(ArEl& first, ArEl& second); 
    void redim(size_t size); 

private: 
    std::size_t rSize; 
    T* rArray; 
}; 

template <typename T, typename T1> 
class ArEl<ArEl<T>> : public ArEl<T1>{ 
    ArEl(size_t size = 0); 
}; 

EDIT:

Ich erhalte diese Fehlermeldung:

error: template parameters not deducible in partial specialization: 
class ArEl<ArEl<T>> : public ArEl<T1>{ 

Antwort

4

Sie sind spezialisiert Ihr Objekt in die falsche Richtung.

template<typename T, typename T1> bedeutet, dass zwei Datentypen zur Verfügung gestellt werden müssen, aber es ist klar, dass das einzige, was Ihre Template-Spezialisierung benötigt, der Datentyp der zugrunde liegenden Arrays ist. Wenn die Erwartung ist, dass ArEl<ArEl<T>> spezialisiert sein, sollte es dauern, nicht mehr als das:

template<typename T> 
class ArEl<ArEl<T>> { 
    /*Blah Blah Blah*/ 
}; 

Es für die Vererbung keine Notwendigkeit und keine Notwendigkeit für einen zweiten Datentyp.

aber ich werde auch hinzufügen: Es gibt nicht wirklich irgendeine Notwendigkeit für diese Spezialisierung auf dem ersten Platz. Wenn Sie nicht die Spezialisierung schreiben überhaupt, sollte der folgende Code immer noch funktionieren, wie sie ist:

ArEl<ArEl<int>> dim2Array(50); 
//I'm assuming ArEl will have a member size() function 
for(size_t index = 0; index < dim2Array.size(); index++) { 
    //I'm assuming ArEl will have an operator[] overload 
    dim2Array[index].redim(30); 
} 
//dim2Array is now 50 int arrays, each of size 30. 

Ich gehe davon aus, dass die Funktionalität sind die beabsichtigen Sie so etwas wie die folgenden zu haben ist, was erforderlich macht Template-Spezialisierung wie das, was ich oben geschrieben:

ArEl<ArEl<int>> dim2Array(50, 30); 
//dim2Array is now 50 int arrays, each of size 30. 

Aber wenn ich du wäre, würde ich die Implementierung von ArEl allein und stattdessen in das Schreiben einer Matrix<T> Klasse (oder möglicherweise Matrix<T, N>, für N-Dimensionen), die Griffe investieren verlassen diese Art von Syntax stattdessen (die Sie mit ArEl<T> erstellen könnten als Bausteine, nebenbei bemerkt), vor allem, weil ich glaube, Sie die Spezialisierungen für ArEl<ArEl<ArEl<int>>> oder tiefer (und ja zum Schreiben verpflichten nicht sind, sind versucht so, wie Sie es zu tun, jede Ebene würde seine eigene Spezialisierung benötigen).

3

eine ganze Klasse Spezialisierung impliziert mit den von der Spezialisierung vorgesehen diejenigen alle Mitglieder zu ersetzen. Das willst du nicht.

Eine Option wäre, alle Mitglieder, die Spezialisierung in einer Basisklasse benötigen: BaseForA<T> wäre spezialisiert, und A<T> würde daraus abgeleitet werden.

würde andere einen Tag Dispatching zu verwenden sein, hier ist ein Beispiel dafür, wie Sie es verwenden, können verschiedene Aktionen zu tun, auf dem Typparameter abhängig.

#include <iostream> 
#include <type_traits> 

template<typename T> 
struct tag {}; 

template<typename T> 
struct A 
{ 
private: 
    template<typename U> 
    A(std::size_t s, tag<A<U>>) 
    { 
     std::cout << "special constructor " << s << "\n"; 
    } 

    A(std::size_t s, ...) 
    { 
     std::cout << "general constructor " << s << "\n"; 
    } 
public: 
    A(std::size_t s = 0) : 
     A(s, tag<T>()) 
    { 

    } 
}; 

int main() 
{ 
    A<int> a; 
    A<A<int>> b; 
    A<A<long>> c; 
    A<long> d; 
} 

Live on Coliru

0

Wenn ich Sie richtig verstanden möchten Sie die spezielle Version der generischen Version und fügen Sie dann etwas oben drauf erben. Das Problem hier ist, dass Sie eine spezialisierte ArEl<ArEl<T>> haben, Sie können keine generische Version davon anfordern.

Die Lösung besteht darin, die generische Version und die spezialisierte Version von verschiedenen Typen zu machen.

template<typename T, bool D=true> 
class ArEl { ... 

template<typename T> 
class ArEl<ArEl<T>>: 
    public ArEl<ArEl<T>, false> { ... 

Aber jetzt das Problem ist, dass ArEl<T, true> und ArEl<T, false> sind unabhängig und nicht kompatibel!

Die Lösung besteht darin, eine gemeinsame Basisklasse für sie einzuführen.

template<typename T> 
class ArElBase { 
    ... all functionality of ArEl 
}; 

template<typename T, bool D=true> 
class ArEl : public ArElBase<T> { 
    using ArElBase<T>::ArElBase; 
    // nothing more 
}; 

und dann die Spezialisierung, unverändert.

Jetzt können Sie ArElBase verwenden, um Ihre Objekte per Zeiger oder Verweis zu übergeben, aber ArEl verwenden, um Objekte selbst zu deklarieren.

Verwandte Themen