减少类模板特化中的代码重复(数组<unique_ptr>)

时间:2017-04-12 10:08:58

标签: c++ templates c++14 template-specialization template-classes

如何减少模板专用类的代码重复?

我正在尝试创建一个类似MyArray的类(std::vector),但在某些函数中接收raw-pointer作为参数。

以下是它的简化版本: -

template<class T> class MyArray{
    T database[10];
    public: T& get(int index){return database[index];}
    void set(int index, T t){
        database[index]=t;
    }
};
template<class T> class MyArray<std::unique_ptr<T>>{
    T* database[10];
    public: T*& get(int index){return database[index];}
    void set(int index, std::unique_ptr<T> t){
        T* tmp=t.release();
        database[index]=tmp;  
    }
};

Here是一项测试: -

class B{};
int main() {
    MyArray<B>   test1;
    MyArray<B*>  test2;
    MyArray<std::unique_ptr<B>> test3;
    test3.set(2,std::make_unique<B>()));
    return 0;
}

问题:请展示一种优雅的方法来减少MyArray中的上述代码重复。

我希望的解决方案可能如下: -

template<class T> class MyArray{
    using U = if(T=std::uniquePtr<X>){X*}else{T};
    U database[10];
    public: U& get(int index){return database[index];}
    void set(int index, T t){
        U u = convert(t);//<-- some special function
        database[index]=u;
    }
};

可能存在一些内存泄漏/损坏。为简单起见,请忽略它  我只想要一个想法/粗略指南。 (不需要提供完整的可运行代码,但我不介意)

在现实生活中,MyArray中有20多个函数,我希望对许多类进行相同的重构。

编辑:我(次要)编辑了一些代码和标记。感谢AndyG和Jarod42。

2 个答案:

答案 0 :(得分:3)

也许你可以将实现细节委托给你提供给你的类的结构,并且你专门化这个结构,而不是MyArray:

template <typename T>
struct Policy {
  using type = T;
  static type convert(T t) { ... }
};

template <typename T>
struct Policy<std::unique_ptr<T>> {
  using type = T*;
  static type convert(T t) { ... }
};

template <typename T, typename P = Policy<T>>
class MyArray
{
  using type = typename P::type;

  void set(int index, T t) { type result = P::convert(t); }
};

答案 1 :(得分:1)

您可能会考虑使用公共基类来实现常用功能:

template<class T>
class Base{
    protected:
    T database[10];
    public:
    T& get(int index){return database[index];} 
};

template<class T> 
class MyArray : public Base<T>{
    public:
    void set(int index, T t){
        this->database[index]=t;
    }
};

template<class T> 
class MyArray<std::unique_ptr<T>> : public Base<T*>
{
    public:
    void set(int index, std::unique_ptr<T>&& t){
        T* tmp=t.release();
        this->database[index]=tmp;   //a little different
    }
};

Demo