2010-07-29 45 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