Reputation: 19146
I have a template SoundRecording.h
:
template <typename T>
class SoundRecording {
public:
explicit SoundRecording(T init);
private:
T data;
};
template <typename T>
SoundRecording<T>::SoundRecording(T init){
data = init;
}
And I can create instances of this template class like this:
SoundRecording<int16_t> recording(INT16_MAX);
What is the best way to convert recording
to a SoundRecording<float>
?
I know I could use a simple method, for example I could declare:
SoundRecording<float> convertInt16ToFloat(SoundRecording<int16_t> input)
But I was wondering whether there was a more elegant way to achieve this using assignment or constructor operators.
Updated following comments: I am looking to define an explicit conversion. In the above example recording.data
is equal to INT16_MAX
after construction. After being converted to a float
it should equal 1.0F
.
Upvotes: 1
Views: 77
Reputation: 56547
You can have a templated conversion operator like
template<class U>
explicit operator SoundRecording<U>() { /*do the conversion here*/ }
Minimal code snippet that exemplifies the 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
}
As @Mooing Duck remarked in the comment, try to mark your conversion operators as explicit
to avoid nasty un-wanted compiler-triggerd conversions.
You can go a bit further and enable your conversion only when T
is convertible to U
or vice-versa, via a combination of std::enable_if
and std::is_convertible
, like so:
template<class U,
typename std::enable_if<std::is_convertible<T, U>::value>::type* = nullptr>
explicit operator X<U>() {return {};}
Upvotes: 4
Reputation: 4216
For an example of allowing this with a copy constructor instead of a casting operator:
#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);
}
Upvotes: 2