How to use the type of a compile time constant primitive as type declaration for other variables?
I am trying to do some template metaprogramming in c++ for SI unit conversion. It comes down to how to automatically determine which primitive precision I need after one plus operator. For example:
template<typename Precision>
class Unit {
public:
Unit(Precision v) : value(v) {}
Precision value;
};
template<typename Precision1, typename Precision2>
struct PrecisionTransform {
constexpr static auto test = (Precision1)1 * (Precision2)1; // Compile time constant
using Type = Precision1; // TODO: ideally typeof(test)
};
template<typename Precision1, typename Precision2>
Unit<PrecisionTransform<Precision1, Precision2>::Type> operator+(const Unit<Precision1>& x, const Unit<Precision2>& y)
{
return Unit<PrecisionTransform<Precision1, Precision2>::Type>(x.value + y.value);
}
int main()
{
Unit<double> a = 2.0;
Unit<float> b = 1.0f;
auto c = a + b;
return 0;
}
or in simple terms, can some thing like this happen?
float a = 1;
typeof(a) b = 2;
It seems quite possible since I've gone this far. But I am not sure how to use
You almost got it. As max66 already pointed out, use decltype
. First of all, you can replace your PrecisionTransform
class with the follwing type alias (you have to #include <utility>
for this):
template <typename Precision1, typename Precision2>
using TransformType = decltype(std::declval<Precision1>() * std::declval<Precision2>());
The std::declval<XYZ>()
is just a more generic way of saying (Precision1)1
which allows you to also use types that don't have accessible constructors (in your case irrelevant as you only use primitives).
Your operator+
is then changed to:
template<typename Precision1, typename Precision2>
Unit<TransformType<Precision1, Precision2>> operator+(const Unit<Precision1>& x, const Unit<Precision2>& y)
{
return Unit<TransformType<Precision1, Precision2>>(x.value + y.value);
}
Note that you got a typo in your version of operator+
(both operands used Precision1
).
As you can see here, the major compilers agree on this.