代码之家  ›  专栏  ›  技术社区  ›  Krumelur

向模板专门化添加方法

  •  6
  • Krumelur  · 技术社区  · 14 年前

    我有一个模板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时才可用。

    4 回复  |  直到 14 年前
        1
  •  5
  •   Aaron McDaid    14 年前

    不需要单独的类来表示特殊行为。部分专门化允许您处理一些MyBuffer<十、 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
    

    编辑: 正如Georg在评论中指出的那样,我的最后几行毕竟不是很有用,所以我删除了它们。

        2
  •  5
  •   Georg Fritzsche    14 年前

    我会选择 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; }
    };
    
        3
  •  1
  •   rlbond    14 年前

    method1 method2 返回对的引用 *this 方法1 事实上的。

        4
  •  1
  •   Beta    14 年前

    诀窍是有一个 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);
      }
    };