gpt4 book ai didi

c++ - 包装 std::vector 类以使查询看起来像 .net List 查询

转载 作者:行者123 更新时间:2023-11-28 01:37:05 25 4
gpt4 key购买 nike

当我从 C# 切换到 C++ 时,最怀念的功能之一是 List 类查询,如查找、查找、存在等,以及 lambda 谓词。

所以,我决定包装 vector 类并享受结果的“语法糖”。

我知道并不是所有的 vector 成员都被重写,这可以作为我的想法的一个例子。

问题是:

这是我的问题的可行解决方案吗?

是否存在会破坏包装类的性能或行为的概念错误?

这里的包装看起来像:

 #include<vector>

template<typename T>
class VectorWrap
{
public:
std::vector<T> v;

VectorWrap() noexcept:v{} {}
VectorWrap(std::initializer_list<T> list)noexcept : v{ list } {}

T& operator[](int i) noexcept { return v[i]; }
const T& operator[](int i) const noexcept { return v[i]; }

void add(const T& a) noexcept { v.push_back(a); }
void push_back(const T& a) noexcept { v.push_back(a); }

void clear() noexcept { v.clear(); }
const auto size() const noexcept { return v.size(); }
const auto begin() const noexcept { return v.begin(); }
const auto end() const noexcept { return v.end(); }
const bool empty() const noexcept { return v.empty(); }

bool contains(const T& a) const noexcept
{
auto x = std::find(v.begin(), v.end(), a);
return x != std::end(v);
}

template<typename Pred>
T find(Pred p) const noexcept
{
auto x = std::find_if(v.begin(), v.end(), p);
return x != std::end(v) ? *x : T{};
}

template<typename Pred>
bool any(Pred p) const noexcept
{
return std::any_of(std::begin(v), std::end(v), p);
}

template<typename Pred>
VectorWrap<T> findall(Pred p) noexcept
{
VectorWrap res;
for (auto* x : v)
if (p(x)) res.push_back(x);
return res;
}

template<typename Pred>
const T& minby(Pred p) const noexcept
{
if (v.size() == 0)
return T{};
return *std::min_element(v.begin(), v.end(), p);
}

template<typename Pred>
const T& maxby(Pred p) const noexcept
{
if (v.size() == 0)
return T{};
return *std::max_element(v.begin(), v.end(), p);
}
};

编辑:

对于评论中的所有那些似乎没有理解我问题背后的想法的人。

我并不声称要完全取代任何容器类。我只是为我经常使用的 vector 的一些功能做了一个例子。出于同样的目的,我公开了底层 vector 。

但这不是重点。真正的重点是背后的“语法糖”。可以输入:

VectorWrap<int> MyWrappedExampleVectorInstance = { 1, 2, 3, 4 };

int result = MyWrappedExampleVectorInstance.find([&](int i) { return i > 1 && i < 5; });

代替:

std::vector<int> MyNonWrappedExampleVectorInstance = { 1, 2, 3, 4 };

std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>> firstMatchOnLambdaPredicate = std::find_if(MyNonWrappedExampleVectorInstance.begin(), MyNonWrappedExampleVectorInstance.end(), [&](int i) { return i > 1 && i < 5; });

int result = *firstMatchOnLambdaPredicate;

我希望您能看出这两个示例在可读性和简洁性方面的差异。

最佳答案

在C++思想中,非常强调数据和算法的分离。这就是 vector 没有 find 方法的原因 - 简单的顺序搜索对 vector 、列表和队列的工作方式相同。

因此,无需在所有这些容器中复制顺序搜索逻辑 - 相反,顺序搜索 find 函数只编写一次(称为算法)并以这样的方式制作它独立于任何能够进行序列迭代的容器。这提供了很多好处——无需在多个容器中重复相同的代码,如果对算法进行了改进,它会自动对所有容器可用,并且通常与避免代码重复相关的其他好处。

这并不总是这样工作 - 例如,关联容器(集合、映射)确实有一个方法 find 定义在它们上面,因为它们的搜索操作不是顺序查找并且需要了解高效的数据表示。

我个人不喜欢 STL 算法的一件事是,它们历来采用一对迭代器,而且提供一对不相关的迭代器很容易出错。但这可以通过 Ranges 解决。

关于c++ - 包装 std::vector 类以使查询看起来像 .net List<T> 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48834116/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com