2016-07-27 5 views
0

Dies wurde wahrscheinlich schon einmal gestellt und beantwortet, aber ich konnte die Suchbegriffe nicht finden, um sie zu finden. Hier ist ein Code, der mein Problem zeigt (als Pseudo-Code gedacht ... bitte bei Bedarf um Klärung bitten).So ermitteln Sie den zugrunde liegenden Vorlagentyp des Vorlagenparameters, der aus einer Klassenvorlage übernommen wurde?

Image.h:

template <class T> 
class Image 
{ 
    public: 
     // Return pointer to data. 
     T* GetValues(); 

     std::vector<T> data_; 

}; 

template <class T> 
T* Image<T>::GetValues() 
{ 
    return &data_[0]; 
} 

SpecialImage.h

class SpecialImage : public Image<float> 
{ 

} 

Stack.h

template<class T> 
class Stack 
{ 
    public: 

     void NegateAllImageValues(); 

     std::vector<T> stackOfImages_; 
}; 

template <class T> 
void Stack::NegateAllImageValues() 
{ 
    for(int i = 0; i < stackOfImages_.size(); ++i) 
    { 
     // Type L should be float if T=SpecialImage, but how to get? 
     L* imageValues = stackOfImages_.at(i).GetValues(); 

     // Loop over values and multiply by -1.0. 
    } 
} 

main.cpp

{ 
    // Create stack of SpecialImages. 
    Stack<SpecialImage> myStack; 

    // Create special image and add some data. 
    SpecialImage mySpecialImage; 
    mySpecialImage.data_.push_back(1.0f); 
    mySpecialImage.data_.push_back(2.0f); 
    mySpecialImage.data_.push_back(3.0f); 

    // Add special image to stack. 
    myStack.stackOfImages_.push_back(mySpecialImage); 

    // Negate all values in all SpecialImages in the stack. 
    myStack.NegateAllImageValues(); 

} 

Meine Frage ist, wie man den Typ L in Stack :: NegateAllImageValues? Mir ist klar, dass ich eine Methode Image :: NegateAllValues ​​schreiben und diese aus Stack :: NegateAllImageValues ​​aufrufen kann, aber ich möchte wissen, ob es eine Möglichkeit gibt, den Typ L auf Stack-Ebene zu bekommen. Ich glaube, ich könnte einen zusätzlichen Template-Parameter an die Funktion Stapel hinzufügen :: NegateAllImageValues ​​wie

template <class T, class L> 
void Stack::NegateAllImageValues() 
{ 
    for(int i = 0; i < stackOfImages_.size(); ++i) 
    { 
     // Type L should be float if T=SpecialImage, but how to get? 
     L* imageValues = stackOfImages_.at(i).GetValues(); 

     // Loop over values and multiply by -1.0. 
    } 
} 

aber dann wird der Typ L nicht die zugrunde liegende Vorlage Art von Bild passen gezwungen.

Gibt es hier einen Konstruktionsfehler? Gibt es eine Möglichkeit, Typ L auf Stapelebene zu bekommen?

+1

Erfassen Sie den Typ, indem Sie hinzufügen: 'mit valueType = T;' zu 'Image' –

+0

Es gibt auch' auto', aber yeah, 'Image' sollte diesen Typ alias haben. – LogicStuff

Antwort

3

Der klassische Weg, dies zu tun, ist ein typedef/Alias ​​in Ihrer Image Klasse zu setzen, so etwas wie

template <typename T> 
class Image { 
public: 
    typedef T value_type; 

    // Other stuff 
}; 

Dann später in Ihrer Stack::NegateAllImageValues() Methode können Sie

template <class T> 
void Stack::NegateAllImageValues() 
{ 
    for(int i = 0; i < stackOfImages_.size(); ++i) 
    { 
     typename T::value_type* imageValues = stackOfImages_.at(i).GetValues(); 

     // Loop over values and multiply by -1.0. 
    } 
} 

solcherlei sagen typedefs werden im Grunde von jeder Vorlagenklasse in der Standardbibliothek verwendet: Beispiel: std::vector<T> enthält (unter anderem) ein Element typedef , das ein Alias ​​für T ist.

Eine Alternative in C++ 11 und höher ist auto stattdessen zu verwenden, zum Beispiel:

template <class T> 
void Stack::NegateAllImageValues() 
{ 
    for(int i = 0; i < stackOfImages_.size(); ++i) 
    { 
     auto* imageValues = stackOfImages_.at(i).GetValues(); 

     // Loop over values and multiply by -1.0. 
    } 
} 

[Plain auto würde als auto* genauso gut funktionieren, aber ich ziehe das letztere, wie es deutlich macht, dass . Sie einen Zeigertyp erwarten]

, schließlich in C++ 11 könnten Sie decltype verwenden den Rückgabetyp von GetValues() zu bekommen:

template <class T> 
void Stack::NegateAllImageValues() 
{ 
    for(int i = 0; i < stackOfImages_.size(); ++i) 
    { 
     using value_type = decltype(stackOfImages_.at(i).GetValues()); 
     value_type imageValues = stackOfImages_.at(i).GetValues(); 

     // Loop over values and multiply by -1.0. 
    } 
} 

Obwohl dies nichts wirklich über auto gewinnt.

+0

Perfekt, danke! – user1777820

Verwandte Themen