我正在使用mArray类,该类实现具有可变维数的数字数据容器

template <typename T>
   class mArray<T>: {
     ...
     std::vector<T> my_data;
   }

另一个类mImage继承自mArray并提供特定于图像的操作,另一个类mDcmImage继承自mImage并提供特定于格式的功能。

我认为这是分离不同类型功能的一种非常干净的方法。

一个示例或mArray功能:逐个元素添加:
// add a mArray to the data [1]
template <typename U>
void operator+= (const mArray<U>& other) {
    if (other.getSizes() != getSizes())
        throw std::invalid_argument {"incompatible sizes"};
    else {
        std::transform (my_data.begin(),
                        my_data.end(),
                        my_data.begin(),
                        my_data.begin(),
                        []( const T &a, const U &b) { return a+b; } );
    }
    return;
}

// add an element to the data [2]
template <typename U>
void operator+= (const U& rhs) {
    assert (!std::is_arithmetic<U>::value);
    std::transform (my_data.begin(),
                    my_data.end(),
                    my_data.begin(),
                    [&rhs]( const T &lhs) { return lhs+rhs; } );
    return;
}

(getSizes()mArray函数)
但是现在我的代码从文件中以及当我使用时加载了mDcmImage<int>
typedef int intensity;
mDcmImage<intensity> im1 ("/tmp/test1.im");
mDcmImage<intensity> im2 ("/tmp/test2.im");
im1 += im2;

然后我得到以下错误:
mArray.hpp required from ‘struct mArray<T>::operator+=(const U&)
           [with U = mDcmImage<int>; T = int]::<lambda(const int&)>’|
mArray.hpp required from ‘void mArray<T>::operator+=(const U&)
           [with U = mDcmImage<int>; T = int]’|
  test.cpp required from here|
mArray.hpp error: no match for ‘operator+’ in ‘lhs + rhs’|

换句话说:尽管我编码了另一个mArray的加法以及一个值的加法,但是当我在主程序中调用+=运算符将两个数组加在一起时,它对单个值使用+=实现。

我已经尝试了几件事,例如
  • 使用std::enable_if<std::is_arithmetic<U>::value >::type*作为operator+=的值版本-不允许使用,因为operator+=严格接受1个参数
  • 同时为operator+=mImage定义了mDcmImage的两个版本-在这些级别上,它还会使用错误的实现。

  • simplified example中,选择了运算符的正确版本-为什么现在不这样做?我看不到为什么重载解析失败。

    最佳答案

    扣除模板参数后,第二个版本将成为完美匹配:

    template <typename U> void operator+= (const U& rhs); // U = mDcmImage<int>
    

    与第一个版本相比,后者需要从mDcmImage转换为mArray:
    template <typename U> void operator+= (const mArray<U>& other); // U = int
    

    因此它是由过载分辨率选择的。

    最简单的解决方法可能是将单值版本修改为仅采用T并依赖隐式转换:
    void operator+= (const T& rhs);
    

    也可以使用SFINAE,例如返回类型:
    template <typename U>
    typename std::enable_if<std::is_arithmetic<U>::value>::type operator+= (const U& rhs);
    

    09-06 17:19