I have a class which implements data types for a huge project. I simplify it here to (actually it is a subclass passing typeID and subTypeID to iots parent class constructor):
template<typename T,uint32_t typeID, uint32_t subTypeID> class TDataType {
private:
T _value;
};
Note that using something similar to variants is not an option in this context. Also type IDs are required, this has nothing to do with OO but with the software configuration. I did include them in this simpel example only to show the complete template parameters.
What I want to achieve is to implement a conversion template which is able to transparently convert from one simple type to the other (for some types (like std::string) I know I will need a specialized template.
So I want something like this (pseudo syntax) for conversion of T1 to T2 both being some TDataType classes:
template<class TDataType<typename T1,uint32_t TYP1, uint32_t STYP1>,
class TDataType<typename T2,uint32_t TYP2, uint32_t STYP2>> convert(TDataType<T1,TYP1,STYP1> &v1,
TDataType<T2,TYP2,STYP2> &v2)
{ v1._value = static_cast<T1>(v2._value); }
Where T1/2, TYP1/2 and STYP1/2 would be deduced from the passed TDataType
So that for example the following could be done:
TDataType<int32_t,1,32> Int{3};
TDataType<double,2,2> Double;
convert(Int,Double); // Set Double to 3.0
Please note that thios conversion is only an example of a use-case, there are many more like operators for example. So I mainly look if this template-template-parameter-parameter deduction is possible at all.
Anothe rexample woul be something like:
template<class TDataType<typename T,uint32_t TYP, uint32_t STYP>,
typename LT>
operator=(LT &lh,TDataType<T,TYP,STYP> &rh)
{ lh = static_cast<LT>(rh._value); }
The simple assignment of TDataType to another TDataType is not an issue as this can be implemented inside of the target class template and use the "local" template type parameter for static_cast.
It's certainly possible, the right syntax is simply:
template<typename T1, uint32_t TYP1, uint32_t STYP1,
typename T2, uint32_t TYP2, uint32_t STYP2>
void convert(TDataType<T1, TYP1, STYP1> from, TDataType<T2, TYP2, STYP2> &to)
{
to = static_cast<T2>(from.value()); // assuming TDataType has a ctor TDataType(T)
}
But it may be better to create a templated converting constructor that directly initializes from another TDataType instance:
template<typename T, uint32_t typeID, uint32_t subTypeID>
class TDataType {
T _value;
public:
TDataType(T value) : _value(value) {}
template<typename P, uint32_t pTypeID, uint32_t pSubTypeID>
TDataType(TDataType<P, pTypeID, pSubTypeID> that) : _value(static_cast<T>(that._value)) {}
template<typename, uint32_t, uint32_t>
friend class TDataType; // to be able to access that._value
};
Alternatively, use a user-defined conversion operator to make different TDataType's convertible to one another.
template<typename T, uint32_t typeID, uint32_t subTypeID>
class TDataType {
T _value;
public:
TDataType(T value) : _value(value) {}
template<typename P, uint32_t pTypeID, uint32_t pSubTypeID>
operator TDataType<P, pTypeID, pSubTypeID>() const {
return static_cast<P>(_value);
}
};
You can further specialize the conversion operator to do different things depending on the target type and/or declare the default specialization as deleted for a finer control of which conversions are allowed.
Then you'll be able to do:
TDataType<int32_t, 1, 32> Int{ 3 };
TDataType<double, 2, 2> Double = Int;