So I'm currently working on upgrading my skills with templates and I'm stuck with something.
I want to, if one of my objects uses floating_point
numbers and I do math operation with another object which is of type integral, to return an object of type floating point.
But I can only know when they're already in the function and I would like to know if there is a way to force our typename to be some defined type.
EDIT: I saw that my post lacked of example so I will show you the function I'm working on.
// Addition : +
template <typename TYP_O1, typename TYP_O2, typename TYP_RE>
requires (std::integral<TYP_O1> || std::floating_point<TYP_O1>) &&(std::integral<TYP_O2> || std::floating_point<TYP_O2>)
MultiArray<TYP_RE> operator+(MultiArray<TYP_O1>& rMultiArr1, MultiArray<TYP_O2>& rMultiArr2){
// Création d'un array qui sera la somme des deux MultiArray un à un
std::vector<TYP_RE> Array;
for(int i = 0 ; i < (int)rMultiArr1.getArray().size() ; i++) {
// On les récupère par référence pour faciliter la lecture.
std::vector<TYP_O1>& Arr1 = rMultiArr1.getArray();
std::vector<TYP_O2>& Arr2 = rMultiArr2.getArray();
// On rajoute la somme à la fin du Array
Array.push_back((TYP_RE)Arr1[i] + Arr2[i]);
}
// On crée le MultiArray de la somme des 2
MultiArray<TYP_RE> result_MultiArr = {rMultiArr1.getDim(), rMultiArr1.getShape(), Array};
// On renvoie ce MultiArray nouvellement crée
return result_MultiArr;
}
(I've just erased the errors check)
So in the template: TYP_O1
is the type of the first object and TYP_O2
is the type of the second object.
TYP_RE
is the return type and THIS is the typename that I want to force to be a double if one of the MultiArray
is of type "floating_point"
(and the other one is "integral")
In general, you can use std::conditional
to choose a type based on a condition.
A basic example:
template<typename LHS, typename RHS>
auto plus(LHS lhs, RHS rhs) -> std::conditional_t<
std::is_same_v<LHS, double> || std::is_same_v<LHS, double>,
double,
int
> {
return lhs + rhs;
}
The return type of plus
will be double
if either of the arguments is a double
, otherwise it will be int
. Note that it doesn't make much sense here because lhs + rhs
is already a double
if either lhs
or rhs
is (assuming they are basic arithmetic types, not including long double
or pointer types).
In your case (since you've added a code snippet), your could do something like this:
template<typename TYP_O1, typename TYP_O2>
using MultiArraySumResult = std::conditional_t<
std::is_floating_point_v<TYP_01>,
MultiArray<TYP_01>,
MultiArray<TYP_02>
>
// or...
template<typename TYP_O1, typename TYP_O2>
using MultiArraySumResult = MultiArray<std::conditional_t<
std::is_floating_point_v<TYP_01> || std::is_floating_point_v<TYP_02>,
double,
int
>>
Then you just use MultiArraySumResult<TYP_O1, TYP_O2>
as your return type. You can even no specify the return type (auto
without trailing return type), put that using
declaration inside the function, and use it for the local variable that you return:
template <typename TYP_O1, typename TYP_O2, typename TYP_RE>
requires (std::integral<TYP_O1> || std::floating_point<TYP_O1>) &&(std::integral<TYP_O2> || std::floating_point<TYP_O2>)
auto operator+(MultiArray<TYP_O1>& rMultiArr1, MultiArray<TYP_O2>& rMultiArr2){
using ReturnType = std::conditional_t<
is_floating_point_v<TYP_01>,
MultiArray<TYP_01>,
MultiArray<TYP_02>
>
ReturnType Array;
// [...]
return ReturnType{rMultiArr1.getDim(), rMultiArr1.getShape(), Array};
}