我正在使用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);