2010-04-06 53 views
3

我試圖附加一個函數對象,用於對模板化類的銷燬進行調用。但是,我似乎無法將函數對象作爲臨時對象傳遞。我得到的警告(如果註釋行xi.data = 5;):將匿名臨時函數對象傳遞給模板化構造函數的問題

warning C4930: 'X<T> xi2(writer (__cdecl *)(void))': 
    prototyped function not called (was a variable definition intended?) 
      with 
      [ 
       T=int 
      ] 

,如果我嘗試使用構造的對象,我得到一個編譯錯誤說:

error C2228: left of '.data' must have class/struct/union 

我對冗長的道歉一段代碼,但我認爲所有組件都需要可見以評估情況。

template<typename T> 
struct Base 
{ 
    virtual void run(T&){} 
    virtual ~Base(){} 
}; 

template<typename T, typename D> 
struct Derived : public Base<T> 
{ 
    virtual void run(T& t) 
    { 
     D d; 
     d(t); 
    } 
}; 

template<typename T> 
struct X 
{ 
    template<typename R> 
    X(const R& r) 
    { 
     std::cout << "X(R)" << std::endl; 
     ptr = new Derived<T,R>(); 
    } 

    X():ptr(0) 
    { 
     std::cout << "X()" << std::endl; 
    } 

    ~X() 
    { 
     if(ptr) 
     { 
      ptr->run(data); 
      delete ptr; 
     } 
     else 
     { 
      std::cout << "no ptr" << std::endl; 
     } 
    } 

    Base<T>* ptr; 
    T data; 
}; 

struct writer 
{ 
    template<typename T> 
    void operator()(const T& i) 
    { 
     std::cout << "T : " << i << std::endl; 
    } 
}; 

int main() 
{ 
    { 
     writer w; 
     X<int> xi2(w); 
     //X<int> xi2(writer()); //This does not work! 
     xi2.data = 15;  
    } 

    return 0; 
}; 

我想這一點的原因是,這樣我可以「某種方式」附加功能對象類型的對象不保持在類中的函數對象本身的一個實例。因此,當我創建一個對象class X時,我不必在其中保留class writer的對象,但只有一個指向Base<T>(我不確定是否需要此處的<T>,但現在它在那裏)。

的問題是,我似乎有創造的writer一個對象,然後把它傳遞給X構造函數,而不是把它像X<int> xi(writer();

我可能會丟失一些完全愚蠢和明顯的這裏,有什麼建議?

+0

'shared_ptr'的實現使用相同的東西(用於刪除),所以它是可行的!你需要一個自定義的Copy構造函數和Assignment Operator來處理內存......所以最好使這個類型可克隆。 – 2010-04-06 13:20:33

+0

有趣的是,我想不出一種方法讓我的函數對象維護狀態,並且只能在刪除時使用默認的構造函數對象。是的,我確實有一個拷貝構造函數和賦值操作符,但是將它們從代碼中剝離出來以使其更「可呈現」:)。謝謝! – Akanksh 2010-04-06 13:29:21

回答

7

看起來像一個「最煩人的解析」問題。嘗試

X<int> xi2 = X<int>(writer()); 

X<int> xi2((writer())); 
+0

不錯,這兩個工作!但令人傷心的是,使用函數對象「在需要時」的美感已經喪失(或需要額外的括號或對構造函數的顯式調用)。謝謝! (哦,我從來沒有聽說過「最令人頭痛的解析」,所以這是新:)) – Akanksh 2010-04-06 13:26:15

+0

@Tyler McHenry值得注意的是,第一個例子不起作用的情況下,類是'noncopyable',因爲它執行類的複製構造函數。 – jwalk 2013-04-04 18:29:33

5

圍繞X<int> xi2((writer()));嘗試一對額外的括號,這將停止編譯器認爲您的預先聲明函數。 (Scott Meyers Effective STL Item 6.)

+0

感謝您的書籍​​參考。 – Akanksh 2010-04-06 13:45:16

5

X<int> xi2(writer());是一個函數調用XI2本身返回X<int>的聲明,並採取作爲參數的函數不帶參數,並返回一個作家。這是一個「最令人頭疼的解析」。

解決方案是要麼做你做過的,避免臨時的,要麼增加更多的括號。