适用于 C++ 中 class 个对象向量的函数
Function that works on vector of class objects in C++
我有一个名为 Edge
的结构,成员 pair<double,double> s
和 pair<double,double> e
。
在 main
函数中,我有一个边向量 vector<Edge> edges
。
我用 Edge
个对象填充它。
现在我想找到特定 Edge x
的索引。
所以我写了一个函数:
int indexOf(vector<Edge>& arr,Edge& k);
函数体在这里无关紧要。
现在我的问题是,
如何使函数像这样工作:
edges.indexOf(x)
无需将边向量作为参数传递?
也许继承std::vector?
#include <iostream>
#include <vector>
using namespace std;
struct Edge
{
Edge(double _s, double _e) : s(_s), e(_e) {}
double s;
double e;
};
bool operator==(const Edge &lhs, const Edge &rhs) {
return lhs.s == rhs.s && lhs.e == rhs.e;
}
class MyVector : public vector<Edge>
{
public:
int index_of(const Edge &e)
{
for (int i = 0; i < this->size(); ++i) {
if (this->at(i) == e)
return i;
}
return -1;
}
};
int main()
{
MyVector v;
for (int i = 0; i < 10; ++i)
v.emplace_back(i, i);
cout << v.index_of(v.at(5)) << endl;
return 0;
}
兄弟你可以做到这一点我在函数定义中提供默认值
例子 :-
int indexOf(Edge& k,vector& arr = yourVector);
但请确保在使用该函数之前将 yourVector 声明为 golbal 变量并将值放入 yourVector 中。如果你想要示例代码评论我。
我也试了一下。我必须说我非常喜欢在那种情况下用 c# 可以做的事情。
我尽量避免继承,答案 here 详细说明了原因。一般来说,我很少继承实现(或扩展为 c# 调用它)。
可以创建一个 class 类似下面的 IndexCheckable 来包装容器。目前它只针对向量实现,但也可以很容易地为其他容器实现它(并使用其他算法来确定索引)。
IndexCheckable 有明确的责任并为其容器提供可检查性。也可以将其隐藏在隐藏容器类型的界面后面(示例中未显示)
#include <iostream>
#include <vector>
#include <algorithm>
template <class T, class Allocator = std::allocator<T>>
struct IndexCheckable {
const std::vector<T,Allocator>& indexable_;
IndexCheckable(const std::vector<T,Allocator>& indexable)
: indexable_(indexable) {
}
int indexOf(const T& item) const {
auto i = std::find(indexable_.begin(), indexable_.end(), item);
return i == indexable_.end() ? -1 : i - indexable_.begin();
}
};
template <class T, class Allocator =
std::allocator<T>> IndexCheckable<T,Allocator> indexCheckable(const std::vector<T,Allocator>& indexable) {
return IndexCheckable<T,Allocator>{indexable};
}
void foo(const IndexCheckable<int>& indexCheckable) {
//Voilla. Check works!!!
indexCheckable.indexOf(5);
}
int main() {
std::vector<int> ivect{0, 1, 2, 5, 6};
foo(ivect);
// or...
auto r1 = indexCheckable(ivect).indexOf(5);
std::cout << "r1: " << r1 << std::endl; //Expects 3
auto r2 = indexCheckable(ivect).indexOf(10);
std::cout << "r2: " << r2 << std::endl; //Expects -1
return 0;
}
我还决定详细说明将 IndexCheckable 隐藏在接口后面并为不同的容器实现它的想法。从使用的角度来看,代码的客户端只需指定某些东西必须是 IndexCheckable(并且忽略容器类型):
#include <iostream>
#include <vector>
#include <list>
#include <array>
#include <algorithm>
#include <iterator>
template <class T>
struct IndexCheckable {
virtual int indexOf(const T& item) const = 0;
protected: ~IndexCheckable(){}
};
template <
template <class, class> class C, //Container
class T, //Item
class A = std::allocator<T>
>
struct IndexCheckableImpl : public IndexCheckable<T> {
const C<T, A>& indexable_;
IndexCheckableImpl(const C<T, A>& indexable)
: indexable_(indexable) {
}
int indexOf(const T& item) const override {
auto i = std::find(indexable_.begin(), indexable_.end(), item);
return i == indexable_.end() ? -1 : std::distance(indexable_.begin(), i);
}
};
template <template<class,class> class C, class T, class A = std::allocator<T>>
IndexCheckableImpl<C,T,A> indexCheckable(const C<T,A>& indexable) {
return IndexCheckableImpl<C,T,A>{indexable};
}
void testItem(const IndexCheckable<int>& indexCheckable, const char* name) {
auto r1 = indexCheckable.indexOf(5);
std::cout << "Test " << name << ": r1: " << r1 << std::endl; //Expects 3
auto r2 = indexCheckable.indexOf(10);
std::cout << "Test " << name << ": r2: " << r2 << std::endl; //Expects -1
}
template <class Container>
void test(const Container& container, const char* name) {
auto checkable = indexCheckable(container);
testItem(checkable, name);
}
int main() {
test(std::vector<int>{0, 1, 2, 5, 6}, "vector");
test(std::list<int>{0, 1, 2, 5, 6}, "list");
return 0;
}
Now my question is, How can make the function work like edges.indexOf(x)
由于继承 std::vector 不是一个好的解决方案(它向继承的代码添加了注意事项),所以好的解决方案是封装您的向量:
class EdgeSequence // or another name
{
public:
size_t indexOf(const Edge& x) const
{
return std::distance(
begin(),
std::find(begin(), end(), x));
}
auto begin() const { return data.begin(); }
auto end() const { return data.end(); }
// TODO: add other functions you used on your initial vector
private:
std::vector<Edge> data;
};
without having to pass the vector of edges as a parameter?
EdgeSequence edges; // TODO: fill with data
auto index = edges.indexOf(your_edge);
我有一个名为 Edge
的结构,成员 pair<double,double> s
和 pair<double,double> e
。
在 main
函数中,我有一个边向量 vector<Edge> edges
。
我用 Edge
个对象填充它。
现在我想找到特定 Edge x
的索引。
所以我写了一个函数:
int indexOf(vector<Edge>& arr,Edge& k);
函数体在这里无关紧要。 现在我的问题是, 如何使函数像这样工作:
edges.indexOf(x)
无需将边向量作为参数传递?
也许继承std::vector?
#include <iostream>
#include <vector>
using namespace std;
struct Edge
{
Edge(double _s, double _e) : s(_s), e(_e) {}
double s;
double e;
};
bool operator==(const Edge &lhs, const Edge &rhs) {
return lhs.s == rhs.s && lhs.e == rhs.e;
}
class MyVector : public vector<Edge>
{
public:
int index_of(const Edge &e)
{
for (int i = 0; i < this->size(); ++i) {
if (this->at(i) == e)
return i;
}
return -1;
}
};
int main()
{
MyVector v;
for (int i = 0; i < 10; ++i)
v.emplace_back(i, i);
cout << v.index_of(v.at(5)) << endl;
return 0;
}
兄弟你可以做到这一点我在函数定义中提供默认值 例子 :- int indexOf(Edge& k,vector& arr = yourVector);
但请确保在使用该函数之前将 yourVector 声明为 golbal 变量并将值放入 yourVector 中。如果你想要示例代码评论我。
我也试了一下。我必须说我非常喜欢在那种情况下用 c# 可以做的事情。
我尽量避免继承,答案 here 详细说明了原因。一般来说,我很少继承实现(或扩展为 c# 调用它)。
可以创建一个 class 类似下面的 IndexCheckable 来包装容器。目前它只针对向量实现,但也可以很容易地为其他容器实现它(并使用其他算法来确定索引)。
IndexCheckable 有明确的责任并为其容器提供可检查性。也可以将其隐藏在隐藏容器类型的界面后面(示例中未显示)
#include <iostream>
#include <vector>
#include <algorithm>
template <class T, class Allocator = std::allocator<T>>
struct IndexCheckable {
const std::vector<T,Allocator>& indexable_;
IndexCheckable(const std::vector<T,Allocator>& indexable)
: indexable_(indexable) {
}
int indexOf(const T& item) const {
auto i = std::find(indexable_.begin(), indexable_.end(), item);
return i == indexable_.end() ? -1 : i - indexable_.begin();
}
};
template <class T, class Allocator =
std::allocator<T>> IndexCheckable<T,Allocator> indexCheckable(const std::vector<T,Allocator>& indexable) {
return IndexCheckable<T,Allocator>{indexable};
}
void foo(const IndexCheckable<int>& indexCheckable) {
//Voilla. Check works!!!
indexCheckable.indexOf(5);
}
int main() {
std::vector<int> ivect{0, 1, 2, 5, 6};
foo(ivect);
// or...
auto r1 = indexCheckable(ivect).indexOf(5);
std::cout << "r1: " << r1 << std::endl; //Expects 3
auto r2 = indexCheckable(ivect).indexOf(10);
std::cout << "r2: " << r2 << std::endl; //Expects -1
return 0;
}
我还决定详细说明将 IndexCheckable 隐藏在接口后面并为不同的容器实现它的想法。从使用的角度来看,代码的客户端只需指定某些东西必须是 IndexCheckable(并且忽略容器类型):
#include <iostream>
#include <vector>
#include <list>
#include <array>
#include <algorithm>
#include <iterator>
template <class T>
struct IndexCheckable {
virtual int indexOf(const T& item) const = 0;
protected: ~IndexCheckable(){}
};
template <
template <class, class> class C, //Container
class T, //Item
class A = std::allocator<T>
>
struct IndexCheckableImpl : public IndexCheckable<T> {
const C<T, A>& indexable_;
IndexCheckableImpl(const C<T, A>& indexable)
: indexable_(indexable) {
}
int indexOf(const T& item) const override {
auto i = std::find(indexable_.begin(), indexable_.end(), item);
return i == indexable_.end() ? -1 : std::distance(indexable_.begin(), i);
}
};
template <template<class,class> class C, class T, class A = std::allocator<T>>
IndexCheckableImpl<C,T,A> indexCheckable(const C<T,A>& indexable) {
return IndexCheckableImpl<C,T,A>{indexable};
}
void testItem(const IndexCheckable<int>& indexCheckable, const char* name) {
auto r1 = indexCheckable.indexOf(5);
std::cout << "Test " << name << ": r1: " << r1 << std::endl; //Expects 3
auto r2 = indexCheckable.indexOf(10);
std::cout << "Test " << name << ": r2: " << r2 << std::endl; //Expects -1
}
template <class Container>
void test(const Container& container, const char* name) {
auto checkable = indexCheckable(container);
testItem(checkable, name);
}
int main() {
test(std::vector<int>{0, 1, 2, 5, 6}, "vector");
test(std::list<int>{0, 1, 2, 5, 6}, "list");
return 0;
}
Now my question is, How can make the function work like
edges.indexOf(x)
由于继承 std::vector 不是一个好的解决方案(它向继承的代码添加了注意事项),所以好的解决方案是封装您的向量:
class EdgeSequence // or another name
{
public:
size_t indexOf(const Edge& x) const
{
return std::distance(
begin(),
std::find(begin(), end(), x));
}
auto begin() const { return data.begin(); }
auto end() const { return data.end(); }
// TODO: add other functions you used on your initial vector
private:
std::vector<Edge> data;
};
without having to pass the vector of edges as a parameter?
EdgeSequence edges; // TODO: fill with data
auto index = edges.indexOf(your_edge);