Reputation: 1
i need to dynamically create arrays containing different numerical types, including char, int, unsigned int, float, double. i'd like to be able to create any two of these arrays and, assuming they're of the same length, implement arithmetic operators such as operator+=
i've been able to implement the array as a template, but i don't know how to implement any arithmetic operators, since i can't know what the other array's type will be at compile time, or even when the first array is created (i will know the type for the array i'm constructing). i looked at std::array, but it doesn't support arithmetic operators. another alternative, which is definitely not elegant (but does work), is to implement a series of type specific operators, such as
MyArray<V> operator+ (const MyArray<float>& addend) const;
MyArray<V> operator+ (const MyArray<double>& addend) const;
MyArray<V> operator+ (const MyArray<int32>& addend) const;
MyArray<V> operator+ (const MyArray<int16>& addend) const;
thanks for any advice.
Upvotes: 0
Views: 197
Reputation:
You will likely have to dispatch your operations by a result type selected by some type traits.
Simplified for a number (no vector):
#include <iostream>
template <typename T>
struct Number {
T value;
Number(T value) : value(value) {}
template <typename U>
explicit Number(U value) : value(value) {}
operator T () const { return value; }
};
#define C_PLUS_PLUS_11 (201103L <= __cplusplus)
template <typename U, typename V>
struct binary_operation_traits {
#if C_PLUS_PLUS_11
typedef decltype(U() + V()) result_type;
#endif
};
#if ! C_PLUS_PLUS_11
template <typename T>
struct binary_operation_traits<T, T> {
typedef T result_type;
};
template <>
struct binary_operation_traits<int, float> {
typedef float result_type;
};
template <>
struct binary_operation_traits<int, double> {
typedef double result_type;
};
// And so on ...
#endif
template <typename U, typename V>
Number<typename binary_operation_traits<U, V>::result_type>
operator + (const Number<U>& a, const Number<V>& b) {
typedef typename binary_operation_traits<U, V>::result_type result_type;
return Number<result_type>(result_type(a) + result_type(b));
}
int main ()
{
Number<int> a(1);
Number<double> b(1.5);
std::cout << a + b << '\n';
return 0;
}
Upvotes: 0
Reputation: 7881
Alright, its probably obvious enough from my comments of everything in this thread that this is a particular sore spot for me. And this is for good reason, I was once like you. I was like, I can overload operators! AMAZING! OVERLOAD ALL THE OPERATORS (this was with a custom image container type). After a while, a few things became clear:
MyArray<T>+MyArray<J>
work as a memberwise plus like T+J
or should it work like a concatenate like 'string+string'?)You COULD do it like (at a namespace scope) (assuming you have a templated cast operator available)
template <typename T, typename J>
MyArray<decltype(T()+J())> operator+(const MyArray<T>& x,const MyArray<J>& y)
{
using K=decltype(T()+J());
MyArray<K> ret(x.size());//or something?
for (size_t i = 0; i < x.size(); i++) {ret[i]=x[i]+y[i];}//could replace with foreach
return ret;
};
Though using the following with vectors just makes more sense. You can wrap it in a "add" call if you want.
std::vector<T> a;//or whatever
std::vector<J> b;//or whatever
std::vector<K> c(a.size());//note: you can still use the decl type here, OR just define it to whatever you actually want it to be
std::transform(a.begin(), a.end(). b.begin(), c.begin(), std::plus<K>());
If you are trying to do this all over the place, and are trying to make a matrix math library, use one like Eigen, it'll save you a lot of work, it'll be strongly typed as a matrix and not a generic collection, and it'll be done with the full math knowledge the Eigen team has.
Upvotes: 1
Reputation: 798
You can use one more template parameter:
template<class V, class T> MyArray<V> operator+ (const MyArray<T>& addend) const;
Then the cast will always be according to your main array type.
Upvotes: 0