通过组合或自由功能扩展STL容器?

bbt*_*trb 0 c++ composition

假设我的应用程序中需要一个新类型,它由一个std::vector<int>扩展的单个函数组成.直接的方式是组合(由于STL容器的继承限制):

class A {
    public:
        A(std::vector<int> & vec) : vec_(vec) {}
        int hash();
    private:
        std::vector<int> vec_
}
Run Code Online (Sandbox Code Playgroud)

这要求用户首先在构造函数中构造一个vector<int>和一个副本,这在我们要处理大量的大向量时是不好的.当然,人们可以写一个传递push_back(),但这引入了可变状态,我想避免.

所以在我看来,我们可以避免复制或保持不可变,这是正确的吗?

如果是这样,最简单(和效率等效)的方法是在命名空间范围内使用typedef和free函数:

namespace N {
typedef std::vector<int> A;
int a_hash(const A & a);
}
Run Code Online (Sandbox Code Playgroud)

这只是在某种程度上感觉不对,因为未来的扩展将"污染"命名空间.此外,调用a_hash(...)any vector<int>是可能的,这可能会导致意外的结果(假设我们对用户必须遵循的A施加约束或者在第一个示例中强制执行)

我的两个问题是:

  • 在使用上述类代码时,如何不牺牲不变性和效率?
  • 何时使用自由函数而不是类/结构中的封装是否有意义?

谢谢!

Jer*_*fin 6

散列是一种算法而非类型,并且可能不应限于任何特定容器类型中的数据.如果你想提供散列,最有意义的是创建一个函数来计算一个哈希值元素(int就像你上面写的那样),然后使用std::accumulatestd::for_each将它应用于集合:

namespace whatever { 
struct hasher { 
    int current_hash;
public:
    hasher() : current_hash(0x1234) {}

    // incredibly simplistic hash: just XOR the values together.
    operator()(int new_val) { current_hash ^= new_val; }
    operator int() { return current_hash; }
};
}

int hash = std::for_each(coll.begin(), coll.end(), whatever::hasher());
Run Code Online (Sandbox Code Playgroud)

请注意,这允许coll是a vector,或者deque你可以使用一对istream_iterators来散列文件中的数据...