首页 > 解决方案 > 特化模板类并添加新接口

问题描述

一个通用模板类Vector。预期用途是让用户专门化泛型Vector并定义任何自定义操作。例如,

using IntVector = Vector<int>;

IntVector operator+ (const IntVector& a, const IntVector& b);

问题是有些操作不能定义为自由函数,比如IntVector& operator+= (const IntVector& b);. 要解决这个问题,您可以通过继承进行专业化,

class IntVector : public Vector<int> {
public:
    IntVector& operator+= (const IntVector& b);
};

IntVector operator+ (const IntVector& a, const IntVector& b);

但是,这有一个问题,在基本模板类上定义的切片运算符返回一个泛型Vector_view而不是IntVector_view支持operator+=. 您将不得不使用与基类相同的主体重载切片运算符,只是返回类型不同,这是令人讨厌的。

是一个相关的问题,建议制作一个包装器对象,这对于每种具体类型来说都相当乏味。有没有什么简单的方法可以创建一个专业化,您可以在其中添加新接口而无需重新定义类型?如果这是唯一的答案,我认为创建通用基类没有意义。

标签: c++

解决方案


你不需要做任何特别的事情+=

如果我误解了这个问题,请纠正我。可以定义诸如operator+=自由函数之类的东西。例如,以下是您定义它的方式std::vector

#include <vector>

std::vector<int>& operator+=(std::vector<int>& a, std::vector<int> const& b) {
    if(b.size() != a.size())
        throw std::logic_error("SIN! SIN! SIN!");

    auto* b_scan = b.data();
    for(int& value : a) {
        value += *b_scan++; 
    }

    return a; 
}

或者,如果您想避免污染全局命名空间,您可以在与您的Vector类相同的命名空间中定义它,并且由于 Argument-Dependent Lookup,它仍然可以正常工作。

其他运营商呢,比如operator[]

不幸的是,类似的东西必须是成员函数operator[] 我们可以允许用户通过创建一个调用用户提供的函数的通用模板来定义它的行为:

class Vector {

    // Stuff
   public:
    value_t& operator[] (int idx);
    const value_t& operator[] (int idx) const;
    // Add this
    auto operator[](T index) -> decltype(get_index(*this, index)) {
        return get_index(*this, index); 
    }
};

用户可以operator[]通过定义来控制get_index. 例如,我们可以为get_indexfor Vector<int>like 提供一个定义:

Vector_view<int> get_index(Vector<int>& v, std::pair<int, int> p) {
    return {v.begin() + p.first, v.begin() + p.second}; 
}

这个定义可以跟的定义之后Vector不一定要前向声明,因为operator[]是模板,编译器还是会找到的。您可以在此处查看一个工作示例。


推荐阅读