2010-07-29 66 views
6

我有一個模板的C++類暴露了一些方法,例如添加方法模板特

template<int X, int Y> 
class MyBuffer { 
public: 
    MyBuffer<X,Y> method1(); 
}; 

現在,我想如果X == Y.我已經這樣做了,露出更多的方法來這個班通過繼承MyBuffer,

template<int X> 
class MyRegularBuffer : public MyBuffer<X,X> { 
public: 
    MyRegularBuffer method2(); 
}; 

現在,問題是我希望能夠做到

MyRegularBuffer<2> buf = ... 
MyRegularBuffer<2> otherBuf = buf.method1().method2(); 

但我不知道如何做到這一點。我試圖想到拷貝構造函數,轉換操作符等,但是我的C++技巧不幸有點生疏。

編輯:我要補充一點,這些對象的創建是相對便宜(和也,也不會發生了很多),這意味着這將是確定做這樣的事情:

MyRegularBuffer<2> buf = ... 
MyRegularBuffer<2> temp = buf.method1(); // Implicit conversion 
MyRegularBuffer<2> otherBuf = temp.method2(); 

的那麼問題是,我怎樣才能定義這樣的轉換。我認爲轉換運算符需要在MyBuffer中,但是我希望它只在X == Y時可用。

+1

完全不可理解。例如,你談論「轉換操作符」,但沒有。發佈一些真實的代碼。 – 2010-07-29 21:15:06

+0

@尼爾,我想用戶已經盡全力問了一個真正的問題。我想我有點理解它。 – 2010-07-29 22:33:42

+0

@Aaron在這種情況下,請分享您的理解。 – 2010-07-29 22:36:30

回答

5

你並不需要一個單獨的類來表示的特殊行爲。部分專業化可讓您專門處理一些MyBuffer < X,Y >個案,併爲他們提供額外的方法。

保持你原來的MyBuffer < X,Y >的聲明,並補充一點:

template<int Y> 
class MyBuffer<Y, Y> { 
public: 
    MyBuffer<Y,Y> method1(); 
    MyBuffer<Y,Y> method2(); 
}; 

MyBuffer<1,2> m12; m12.method2(); // compile fail, as desired, as it doesn't have such a method because 1 != 2 
MyBuffer<2,2> m22; m22.method2(); // compile success 

編輯:我最後的臺詞更是畢竟是非常有用的,因爲在評論中指出的喬治,所以我刪除了它們。

+1

唯一的缺點是method1()必須在MyBuffer 中重新實現,否則當您嘗試調用MyBuffer :: method1()時編譯器會抱怨未知方法。 AFAIK,沒有辦法讓MyBuffer :: method1()將其實現委託給MyBuffer :: method1(),而不指定不同的模板參數,其中X!= Y. – 2010-07-29 23:08:59

+0

從MyBuffer派生出來將不起作用 - 它不會不知道派生類,因此不能從'method1()'返回適當的類型。 – 2010-07-29 23:17:11

+0

@Georg,我不明白。你能更具體地說明哪條線會失敗嗎?我已編譯我的代碼,它的工作原理。但我必須承認,我錯誤地將最後一行復制到了「MyRegularBuffer類」。現在會更新。 – 2010-07-29 23:21:35

1

如果method1method2返回對*this的引用,就可以做你想做的事。否則,您將需要進行轉換,或者虛擬method1

+0

即使method1()返回此值,您仍然無法從其返回值調用method2(),因爲method2()不是MyBuffer 的接口的一部分。 – wilhelmtell 2010-07-29 20:51:04

+0

您能否詳細說明虛擬方法?我不知道我得到了...我面臨的問題是契約,實現將是相同的(如果X == Y,對象在內存中是相同的,所以我可以做一個重新解釋)。 – Krumelur 2010-07-29 20:53:56

+0

wilhelmtell,是的,正是我的意思。你更快:) – Krumelur 2010-07-29 20:54:45

1

關鍵是有一個MyRegularBuffer::method1調用MyBuffer::method1,然後一直到最終MyBuffer<X,X>轉換成MyRegularBuffer<X>

template<int X> 
class MyRegularBuffer : public MyBuffer<X,X> 
{ 
public: 

    MyRegularBuffer<X>() 
    {} 

    MyRegularBuffer<X>(MyBuffer<X,X>) 
    { 
    // copy fields, or whatever 
    } 

    MyRegularBuffer<X> method2(); 

    MyRegularBuffer<X> method1() 
    { 
    MyRegularBuffer<X> ret(MyBuffer<X,X>::method1()); 
    return(ret); 
    } 
}; 
+0

謝謝。是的,這是一個好主意,但在我的情況下,它不會在@Aaron McDaid的解決方案中添加任何內容,因爲我必須再次實現method1(method1實際上是一些方法)。 – Krumelur 2010-07-30 07:26:35

3

我會去CRTP這裏:

template<int X, int Y, class Derived> 
struct MyBufferBase { 
    // common interface: 
    Derived& method1() { return *static_cast<Derived*>(this); } 
}; 

template<int X, int Y> 
struct MyBuffer : MyBufferBase<X, Y, MyBuffer<X,Y> > { 
    // basic version 
}; 

template<int X> 
struct MyRegularBuffer : MyBufferBase<X, X, MyRegularBuffer<X> > { 
    // extended interface: 
    MyRegularBuffer& method2() { return *this; } 
}; 
+0

+1謝謝你提醒我。 – 2010-07-29 23:29:53

+0

謝謝。這絕對是一個好主意。 – Krumelur 2010-07-30 07:29:15

+0

如果我可以給出多於一個答案的標記,我會標記爲答案,但是現在Aaron McDaid的解決方案實際上非常順利,因爲我的方法很薄(這是一個包裝類)。 – Krumelur 2010-07-30 07:31:14