添加不同类型的数组(c ++)

时间:2014-04-18 13:46:26

标签: c++ arrays templates

我需要动态创建包含不同数字类型的数组,包括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;

感谢任何建议。

3 个答案:

答案 0 :(得分:1)

好吧,从我对这个帖子中的所有内容的评论来看,这可能是显而易见的,这对我来说是一个特别的痛处。这是有充分理由的,我曾经和你一样。我当时想,我可以超载运营商!惊人!超载所有操作员(这是使用自定义图像容器类型)。过了一会儿,有些事情变得清晰了:

  1. 操作员难以正确声明,特别是模板化的操作员。
  2. 模板化运算符不能明确设置其类型,只能隐式设置。
  3. 操作顺序始终没有意义。
  4. 运算符必须使用异常作为“失败”模式,这在所有情况下都不理想,或者如果在编译时可以检测到失败,则使用“enable-if”类型语法。
  5. 操作员意识很难记录/阐明。对操作员应该“做”的不同解释使得很难弄清楚。 (MyArray<T>+MyArray<J>是否应该像成员一样加上T+J,或者它应该像'string + string'这样的连接工作?)
  6. 操作符必须按值返回,这可能会导致开销,如果您的移动未正确设置/您不在C ++ 11中/因任何原因返回值不会发生。
  7. 总的来说,编写自己的容器类型是重做STL已经完成的大量工作的好方法。
  8. 你可以这样做(在命名空间范围内)(假设你有一个模板化的强制转换操作符)

    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;
}