2014-12-03 36 views
0

我試圖重載Python包裝的算術運算符。實現:模板<ClassDerivingFromBase,不>

我包裝我的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} 

在所有這些情況下,左操作數導出來自對象,而正確的不是。

是否有可能建立一個單一的模板功能,有效地做:

template< <DerivedFromBase, Not> 
operator + (DerivedFromBase der, Not x) { 
    return der + DerivedFromBase{x}; 
} 

即它僅捕獲其中左操作數從Object派生的情況,而右邊的一個沒有。

它將右操作數提升爲與左邊相同的類型。

然後der + DerivedFromBase{x}調用將在DerivedFromBase中定義的+運算符。

+0

也許作爲illy的問題,但爲什麼你在這種情況下使用初始化列表? – 2014-12-03 08:54:02

+2

so'template :: value &&!std :: is_base_of :: value,int> = 0>'? (或者,標籤調度可能更乾淨) – 2014-12-03 09:14:09

回答

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 
+0

這是T.C.的模板函數返回類型解決方案的替代方案。它編譯並運行在gcc 4.9.1上。 – 2014-12-03 23:20:55

相關問題