我有一个类似矢量的类,它包含"T"
类型的对象数组,我想实现4个算术运算符,它们将对每个项应用操作:
// Constructors and other functions are omitted for brevity.
template<class T, unsigned int D>
class Vector {
public:
// Add a value to each item: naive implementation.
void operator += (const T&) {
for (int i = 0; i < D; ++i) {
data[i] += value;
}
}
void operator -= (const T&) { ... }
void operator *= (const T&) { ... }
void operator /= (const T&) { ... }
private:
T items[D];
};
因为运算符将包含相同的样板代码(循环遍历每个元素并应用适当的操作),我认为我可以概括它:
template<class T, unsigned int D>
class Vector {
public:
void operator += (const T& value) { do_for_each(???, value); }
void operator -= (const T& value) { do_for_each(???, value); }
void operator *= (const T& value) { do_for_each(???, value); }
void operator /= (const T& value) { do_for_each(???, value); }
private:
void
do_for_each(std::binary_function<void, T, T>& op, T value) {
std::for_each(data, data + D, std::bind2nd(op, value));
}
T data[D];
};
现在,问题是,如何传递一个带有两个内在类型的运算符并将void
返回到do_for_each
,如上例所示? C ++不允许我对内在类型执行此操作(如果"T::operator+="
为"T"
),"int"
将无效。
答案 0 :(得分:8)
首先,您应该从运算符+ =返回一个引用,因为您以后可以使用它们来实现operator +,operator-等等。我会相应地改变它。
此外,你的do_for_each必须是一个模板,因为它必须知道函数对象的精确类型,因为二进制函数对象不是多态类。对于实际操作,您希望使用std::transform
:
template<class T, unsigned int D>
class Vector {
public:
Vector& operator += (const T& value) {
do_for_each(std::plus<T>(), value);
return *this;
}
Vector& operator -= (const T& value) {
do_for_each(std::minus<T>(), value);
return *this;
}
Vector& operator *= (const T& value) {
do_for_each(std::multiplies<T>(), value);
return *this;
}
Vector& operator /= (const T& value) {
do_for_each(std::divides<T>(), value);
return *this;
}
private:
template<typename BinFun>
void do_for_each(BinFun op, const T& value) {
std::transform(data, data + D, data, std::bind2nd(op, value));
}
T data[D];
};
std::transform只会将每个元素传递给函数对象,并将结果返回给作为第三个参数给出的迭代器。
答案 1 :(得分:2)
你应该真正了解Boost Operators,这是一个仅限标题的库,可以真正简化创建正交和一致算术运算符重载的过程。
具体来说:您可能会发现从boost::operators::integer_arithmatic<T>
派生可以为您节省大量的课程重复次数。
答案 2 :(得分:1)
我认为litb是在正确的轨道上并回答了确切的问题 但我认为这是错误的解决方案。
我宁愿不使用do_for_each(),而是直接使用std :: transform():
template<class T, unsigned int D>
class Vector
{
public:
Vector& operator += (const T& value) {
std::transform(data, data + D, data, std::bind2nd(std::plus<T>(),value));
return *this;
}
Vector& operator -= (const T& value) {
std::transform(data, data + D, data, std::bind2nd(std::minus<T>(),value));
return *this;
}
Vector& operator *= (const T& value) {
std::transform(data, data + D, data, std::bind2nd(std::multiplies<T>(),value));
return *this;
}
Vector& operator /= (const T& value) {
std::transform(data, data + D, data, std::bind2nd(std::divides<T>(),value));
return *this;
}
private:
T data[D];
};