2010-11-04 51 views
11

說我有一個模板類:在C++中專門調用函數的非專用版本?

template <typename T> 
class foo { 
    void do_someting(T obj) { 
    // do something generic... 
    } 
}; 

,我想專門do_something,但在它我想稱之爲「正常」 do_something功能:

template<> 
void foo<MyObj>::do_something(MyObj obj) { 
    // do something specific... 
    // and ALSO do something generic! 
} 

是有辦法參考到我的專門功能內的do_something的正常版本?或者我只需要複製代碼?我知道我可以用這樣的方式來重構foo,這樣我就不會有這個確切的問題,但是因爲它發生了,我不能真正修改「真正的」foo,因爲它是嚴重共享的代碼。)

+4

對於MyObj類型,沒有「do_something」的「正常」版本 - 模板專門化的全部效果是*替換*您將從基本模板獲得的實例化,並且使用類/函數在專業化中定義。 – 2010-11-04 17:11:21

+0

可能的重複[如何獲得一個專門的模板來使用非特化版本的成員函數?](http://stackoverflow.com/questions/347096/how-can-i-get-a-specialized-template-使用非特定版本的成員) – 2010-11-04 17:12:37

+1

對,但編譯器知道foo中的代碼 :: do_something,沒有理由爲什麼它不能讓我以某種方式引用它。我完全願意相信這種語言功能根本不存在,但是---這正是我想要發現的。 – 2010-11-04 17:13:41

回答

7

不可以。您的專業化是MyObj類型參數唯一存在的定義。但是,考慮修改FOO模板以這種方式,這將是透明的模板的當前用戶:

template<typename T> 
class foo { 
    void prelude(T &obj){ // choose a better name 
    /* do nothing */ 
    } 
    void do_something(T obj){ 
    prelude(obj); 
    // do something generic... 
    } 
}; 

然後定義爲前奏專業化:

template<> 
void foo<MyObj>::prelude(MyObj &obj){ 
    // do something specific 
} 

這是有點類似結構爲main use case for private virtual members。 (排序,不是真的,但這是什麼啓發我在這個答案。)

+0

這看起來像Sutter的NVI的模板世界比喻! – 2017-08-02 14:57:36

1

你也可以考慮一個不是MyObj類型,但隱式轉換爲它,但最好的方法是重構,也許提取普通通用的東西。

#include <iostream> 
#include <boost/ref.hpp> 
typedef int MyObj; 


template <typename T> 
struct foo { 
    void do_something(T obj) { 
    // do something generic... 
    std::cout << "generic " << obj << '\n'; 
    } 
}; 

template<> 
void foo<MyObj>::do_something(MyObj obj) { 
    // do something specific... 
    std::cout << "special " << obj << '\n'; 
    // and ALSO do something generic! 
    foo<boost::reference_wrapper<MyObj> >().do_something(boost::ref(obj)); 
} 

int main() 
{ 
    foo<int> f; 
    f.do_something(10); 
} 
0

是的,這實際上很簡單。您只需讓函數的主要通用版本作爲「實現」通用函數的傳遞,其不會變得部分專用,那麼您可以根據需要從初始函數的專用版本調用該函數。

template <typename T> 
class foo 
{ 
    void do_something(T obj) 
    { 
    do_something_impl(obj); 
    } 

    void do_something_impl(T obj) 
    { 
    // do something generic... 
    } 
}; 

現在專業化可以調用通用版本不會有問題:

template<> 
void foo<MyObj>::do_something(MyObj obj) 
{ 
    // do something specific... 
    do_something_impl(obj); //The generic part 
} 

我覺得這更接近你的初衷不是史蒂夫M.的答案,是我做什麼,當面對這個問題。