2017-10-11 2 views
1

J'ai un modèle SoundRecording.h:Comment convertir des classes créées à l'aide de modèles C++?

template <typename T> 
class SoundRecording { 
public: 
    explicit SoundRecording(T init); 
private: 
    T data; 
}; 

template <typename T> 
SoundRecording<T>::SoundRecording(T init){ 
    data = init; 
} 

Et je peux créer des instances de cette classe de modèle comme celui-ci:

SoundRecording<int16_t> recording(INT16_MAX); 

Quelle est la meilleure façon de convertir recording à un SoundRecording<float>?

Je sais que je pourrais utiliser une méthode simple, par exemple, je pourrais déclarer:

SoundRecording<float> convertInt16ToFloat(SoundRecording<int16_t> input) 

Mais je me demandais s'il y avait une façon plus élégante pour y parvenir en utilisant des opérateurs d'affectation ou d'un constructeur.

Mise à jour des commentaires suivants: Je cherche à définir une conversion explicite. Dans l'exemple ci-dessus recording.data est égal à INT16_MAX après la construction. Après avoir été converti en float, il doit être égal à 1.0F.

+0

Vous ne savez pas actuellement quelles conversions vous voulez être disponibles. Voulez-vous dire que vous voulez que 'SoundRecording ' soit convertible en 'SoundRecording ' si 'T' est convertible en' U'? Et voulez-vous des conversions explicites ou implicites, et cela ne devrait-il fonctionner que si 'T' est implicitement convertible en' U'? – Justin

+1

Cela dépend de ce que vous appelez "élégant". La façon dont vous avez décrit fonctionne; qu'est-ce que vous essayez d'améliorer exactement? – anatolyg

+0

Pour moi, la conversion semble être de la responsabilité de l'objet 'SoundRecording', plutôt que d'une méthode statique distincte. Pas vraiment un fan des méthodes "utilitaires" si je peux les éviter. – donturner

Répondre

4

Vous pouvez avoir un opérateur de conversion basé sur un modèle comme

template<class U> 
explicit operator SoundRecording<U>() { /*do the conversion here*/ } 

extrait de code minimal qui illustre la technique:

template<class T> 
struct X 
{ 
    template<class U> 
    explicit operator X<U>() {return {};} 
}; 

int main() 
{ 
    X<int> x; 
    auto y = static_cast<X<float>>(x); // conversion 
} 

Live on Coliru

Comme @Mooing Canard fait remarquer dans le commentaire, essayez de marquez vos opérateurs de conversion comme explicit pour éviter de mauvaises conversions compilateur-triggerd indésirables.

Vous pouvez aller un peu plus loin et permettre à votre conversion que lorsque T est convertible en U ou vice-versa, par une combinaison de std::enable_if et std::is_convertible, comme ceci:

template<class U, 
     typename std::enable_if<std::is_convertible<T, U>::value>::type* = nullptr> 
explicit operator X<U>() {return {};} 
+1

préfère 'l'opérateur explicite S ...()' –

+0

Pourquoi ne pas faire la conversion en tant que constructeur au lieu d'un opérateur de conversion? – Justin

+0

@Justin Vous pouvez également faire cela, mais cela permet la conversion * après * construction si l'on veut. – vsoftco

2

Pour un exemple de permettre à cette avec un constructeur de copie au lieu d'un opérateur de diffusion:

#include <cstdint> 

template <typename T> 
class SoundRecording { 
public: 
    SoundRecording(); 

    template <typename U> 
    SoundRecording(const SoundRecording<U>& other); 

private: 
    T *data; 

    template <typename U> 
    friend class SoundRecording; 
}; 

template <typename T> 
SoundRecording<T>::SoundRecording(){ 
    data = new T[10]; 
} 

template <typename T> 
template <typename U> 
SoundRecording<T>::SoundRecording(const SoundRecording<U>& other){ 
    data = new T[10]; 
    for (int i = 0; i < 10; ++i) { 
     data[i] = static_cast<T>(other.data[i]); 
    } 
} 

int main(){ 
    SoundRecording<int16_t> recording16; 
    SoundRecording<float> recordingFloat(recording16); 
}