2016-02-12 44 views
1

我有一個純粹的虛擬模型接口如何處理在C++中已知模板參數數量的虛擬模板函數?

class ModelInterface { 
public: 
    virtual ~ModelInterface() {} 
    virtual double get_value(double scaleFactor) = 0; 
}; 

,要求所有衍生車型來實現get_value()功能。模型的實現可能看起來像

class Model : public ModelInterface { 
public: 
    Model(double value) : _value(value) {} 
    double get_value(double scaleFactor) { 
    return _value * scaleFactor; 
    } 
private: 
    double _value; 
}; 

在主程序的開始,創建了一個模型,並用一個接口指針處理它

int main() 
{ 
    ModelInterface *model = new Model(5.3); 

在一些其他的點,該模型被用來計算所需的值

double scale_factor = 2.2; 
    double value = model->get_value(scale_factor); 
    // do something with the value 

    return 0 
} 

現在我需要與一些其它類型的數目來替換類型double在功能double get_value(double scaleFactor),在這種情況下,一個個在處理自動分化時,我們稱之爲adouble。不過,我仍然需要雙倍版本。有時我需要衍生物,那麼函數應該用adouble類型來調用。如果我不需要派生信息,我想調用double類型的函數來節省資源。我希望能夠像做

double scale_factor1; 
double value1 = model->get_value(scale_factor1); 
adouble scale_factor2; 
adouble value2 = model->get_value(scale_factor2); 

我的第一個目的是爲了增加一個模板參數到行virtual double get_value(double scaleFactor) = 0;,這樣template <class T> virtual T get_value(T scaleFactor) = 0;,但是GCC告訴我虛擬模板是不允許的。下一個解決方案,我發現是使整個虛擬類模板,而不僅僅是功能,如

template <class T> 
class ModelInterface { 
public: 
    virtual ~ModelInterface() {} 
    virtual T get_value(T scaleFactor) = 0; 
}; 

但是,這並沒有解決我的問題,因爲我只有模型的一個實例,該實例會被綁定爲double或者double(或者任何其他類型),但是我不能用不同的參數類型調用同一個對象的函數get_value()

我還遇到了相當複雜的結構與傭工和訪客,以及任何應該能夠解決一般問題。不過,我懷疑我的案例是否有任何簡單的解決方案,因爲我想要使用的不同類型的數量是固定的(2),並且類型也是已知的(doubleadouble)。當然,我希望避免爲每種類型實現兩次函數get_value(),因爲所使用的算法對於兩種類型都完全相同,並且它將是代碼的大量重複。

回答

3

我建議你有重載輸入接口,但在實施的因素普通代碼模板:

class ModelInterface { 
public: 
    virtual ~ModelInterface() {} 
    virtual double get_value(double scaleFactor) = 0; 
    virtual adouble get_value(adouble scaleFactor) = 0; 
}; 

class Model : public ModelInterface { 
public: 
    Model(double value) : _value(value) {} 
    double get_value(double scaleFactor) { 
    return get_value_impl(scaleFactor); 
    } 
    adouble get_value(adouble scaleFactor) { 
    return get_value_impl(scaleFactor); 
    } 
private: 
    template<typename T> T get_value_impl(T scaleFactor) { 
    return _value * scaleFactor; 
    } 
    double _value; 
}; 
1

在特定情況下,我不得不在基地兩個純虛函數(其中一個用於double,另一個用於adouble),這將簡單地將計算轉發到每個孩子班級的模板實現。

0

作爲替代其他建議 - 考慮使用boost::variantboost::any

定義您的界面,我們將與變量值類型的發揮:

class ModelInterface { 
public: 
    virtual ~ModelInterface() {} 

    using value = boost::variant<double, adouble>; 
    virtual value get_value(value scaleFactor) const = 0; 
}; 

而且使用boost::static_visitor實現模型:

class Model : public ModelInterface { 
public: 
    Model(double val) : value_visitor(val) {} 
    virtual value get_value(value val) const { 
     return boost::apply_visitor(value_visitor, val); 
    } 
private: 

    struct impl : boost::static_visitor<ModelInterface::value> 
    { 
      impl(double value) : value_(value) {} 
      double value_; 

      template <typename T> 
      value operator()(T val) const 
      { 
       return static_cast<T>(val * value_); 
      } 
    }; 
    impl value_visitor; 
};