扩展 std::vector 是个好主意吗?

Is it a good idea to extend std::vector?

本文关键字:好主意 std vector 扩展      更新时间:2023-10-16

稍微使用javascript,我意识到与C++相比,开发速度更快,因为由于通常不适用的原因而减慢了写作速度。总是通过.begin().end()通过我的所有应用程序是不舒服的。

我正在考虑扩展std::vector(更多的是通过封装而不是继承),它主要可以遵循javascript方法的约定,例如

.filter([](int i){return i>=0;})
.indexOf(txt2)
.join(delim)
.reverse()

而不是

auto it = std::copy_if (foo.begin(), foo.end(), std::back_inserter(bar), [](int i){return i>=0;} );
ptrdiff_t pos = find(Names.begin(), Names.end(), old_name_) - Names.begin();
copy(elems.begin(), elems.end(), ostream_iterator<string>(s, delim)); 
std::reverse(a.begin(), a.end());

但是,我想知道这是否是一个好主意,为什么已经没有C++库用于这种常见的日常功能?这样的想法有什么问题吗?

这个想法没有任何继承性错误,除非你尝试多态地删除向量。

例如:

auto myvec = new MyVector<int>;
std::vector<int>* myvecbase = myvec;
delete myvecbase; // bad! UB
delete myvec; // ok, not UB

这是不寻常的,但仍可能是错误的源头。

但是,我仍然推荐它。

要获得添加的功能,您必须拥有自己的向量的实例,这意味着您必须将任何其他现有向量复制或移动到您的类型中。它不允许将函数与向量的引用一起使用。

例如,请考虑以下代码:

// Code not in your control:
std::vector<int>& get_vec();
// error! std::vector doesn't have reverse!
auto reversed = get_vec().reverse();
// Works if you copy the vector to your class
auto copy_vec = MyVector<int>{get_vec()};
auto reversed_copy = copy_vec.reverse();

此外,它仅适用于矢量,而我可以看到该实用程序在其他容器类型中具有这些功能。


我的建议是让你提出的函数自由 - 而不是让它们成为你的子向量类的成员。这将使它们适用于任何实例或引用,并且还可以重载其他容器类型。这将使你的代码更标准(不使用你自己的容器集),并且更容易维护。

如果你觉得需要为容器类型实现许多函数式实用程序,我建议你寻找一个为你实现它们的库,即ranges-v3,它正在走向标准化。


在参数的另一边,有继承 STL 类的有效用例。例如,如果处理泛型代码并希望存储可能为空的函数对象,则可以从std::tuple(私下)继承以利用空基类优化。

此外,我有时碰巧存储特定数量的相同类型的元素,这些元素在编译时可能会有所不同。我确实扩展了std::array(私下)以简化实施。

但是请注意这两种情况:我使用它们来简化泛型代码的实现,并且我私下继承了它们,这不会将继承暴露给其他类。

包装器可用于创建更流畅的 API。

template<typename container >
class wrapper{
public:
wrapper(container const& c) : c_( c ){}
wrapper& reverse() {
std::reverse(c_.begin(), c_.end());
return *this;
}
template<typename it>
wrapper& copy( it& dest ) {
std::copy(c_.begin(), c_.end(), dest ); 
return *this;
}
/// ...
private:    
container c_;
};

然后可以使用包装器来"美化"代码

std::vector<int> ints{ 1, 2, 3, 4 };
auto w = wrapper(ints);    
auto out = std::ostream_iterator<int>(std::cout,", ");
w.reverse().copy( out );

在此处查看工作版本。