我正在尝试为Python包装器重载算术运算符。
我用:
包装我的Python原语class Float : Object { ... };
class Long : Object { ... };
:
我正在尝试:
Float F{3.14};
cout << F+3; // <-- overload F+3 by promoting 3, so F+Float{3}
类似地,
Long L{100};
cout << L+1; // L+Long{1}
在所有这些情况下,左操作数派生自Object,而右操作数则不派生。
是否有可能构建一个有效的单一模板化函数:
template< <DerivedFromBase, Not>
operator + ( DerivedFromBase der, Not x ) {
return der + DerivedFromBase{x};
}
即。它只捕获左操作数派生自Object的情况,而右操作数则不会。
它将右操作数提升为与左边相同的类型。
然后der + DerivedFromBase{x}
调用将在DerivedFromBase中定义的+运算符。
答案 0 :(得分:1)
在结果之间使用std::enable_if
,std::is_base_of
和逻辑运算符,只有满足条件,才能构造一个返回类型为T(且有效)的函数:
template<typename T, typename U>
typename std::enable_if<
std::is_base_of<Object, T>::value && !std::is_base_of<Object, U>::value, T
>::type
operator + (const T& i1, const U& i2) {
return i1 + T(i2);
}
然后是完整的示例代码:
#include <iostream>
#include <type_traits>
using std::cout;
using std::endl;
struct Object {
virtual ~Object() {}
};
struct Float : public Object {
constexpr explicit Float(float v) : val(v) {};
float val;
Float operator + (const Float& f) const {
cout << "Float(" << val << ") + Float(" << f.val << ") = ";
return Float(val + f.val);
}
};
struct Long : public Object {
constexpr explicit Long(long v) : val(v) {};
long val;
Long operator + (const Long& l) const {
cout << "Long(" << val << ") + Long(" << l.val << ") = ";
return Long(val + l.val);
}
};
template<typename T, typename U>
typename std::enable_if<
std::is_base_of<Object, T>::value && !std::is_base_of<Object, U>::value, T
>::type
operator + (const T& i1, const U& i2) {
cout << "templated ";
return i1 + T(i2);
}
int main(int argc, char*argv[]) {
Long L(100);
cout << (L+1).val << endl;
cout << (L+L).val << endl;
Float F(20.0f);
cout << (F+1).val << endl;
cout << (F+F).val << endl;
return 0;
}
输出:
templated Long(100) + Long(1) = 101
Long(100) + Long(100) = 200
templated Float(20) + Float(1) = 21
Float(20) + Float(20) = 40