实现:template <classderivingfrombase,not =“”> </classderivingfrombase,>

时间:2014-12-03 08:49:18

标签: c++ templates

我正在尝试为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中定义的+运算符。

1 个答案:

答案 0 :(得分:1)

在结果之间使用std::enable_ifstd::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