我需要动态创建包含不同数字类型的数组,包括char,int,unsigned int,float,double。我希望能够创建这些数组中的任何两个,并假设它们具有相同的长度,实现算术运算符,如operator + =
我已经能够将数组实现为模板,但我不知道如何实现任何算术运算符,因为我无法知道其他数组的类型在编译时是什么类型,甚至是第一个数组被创建(我将知道我正在构建的数组的类型)。我看了std :: array,但它不支持算术运算符。另一种选择,绝对不优雅(但确实有效),是实现一系列特定类型的运算符,例如
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;
感谢任何建议。
答案 0 :(得分:1)
好吧,从我对这个帖子中的所有内容的评论来看,这可能是显而易见的,这对我来说是一个特别的痛处。这是有充分理由的,我曾经和你一样。我当时想,我可以超载运营商!惊人!超载所有操作员(这是使用自定义图像容器类型)。过了一会儿,有些事情变得清晰了:
MyArray<T>+MyArray<J>
是否应该像成员一样加上T+J
,或者它应该像'string + string'这样的连接工作?)你可以这样做(在命名空间范围内)(假设你有一个模板化的强制转换操作符)
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;
};
虽然使用以下向量只是更有意义。如果需要,可以将其包装在“添加”调用中。
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>());
如果你试图在整个地方做这个,并且正在尝试制作一个矩阵数学库,使用像Eigen这样的它,它将为你节省大量的工作,它将被强类型化为矩阵和不是一个通用的集合,它将完成Eigen团队拥有的完整数学知识。
答案 1 :(得分:0)
您可以再使用一个模板参数:
template<class V, class T> MyArray<V> operator+ (const MyArray<T>& addend) const;
然后,演员表将始终根据您的主阵列类型。
答案 2 :(得分:0)
您可能必须按某些类型特征选择的结果类型调度您的操作。
简化为数字(无向量):
#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;
}