gpt4 book ai didi

c++ - 如何定义双括号/双迭代器运算符,类似于 Vector of Vectors'?

转载 作者:可可西里 更新时间:2023-11-01 14:55:22 34 4
gpt4 key购买 nike

我正在移植使用非常大的 float 组的代码,这可能会触发从 c 到 c++ 的 malloc 失败。我问了一个问题,关于我应该使用 vectors 还是 deques 和 Niki Yoshiuchi慷慨地向我提供了这个安全包装类型的例子:

template<typename T>
class VectorDeque
{
private:
enum TYPE { NONE, DEQUE, VECTOR };
std::deque<T> m_d;
std::vector<T> m_v;
TYPE m_type;
...
public:
void resize(size_t n)
{
switch(m_type)
{
case NONE:
try
{
m_v.resize(n);
m_type = VECTOR;
}
catch(std::bad_alloc &ba)
{
m_d.resize(n);
m_type = DEQUE;
}
break;
}
}
};

我需要一个 vector 的二维 vector/双端队列的双端队列,所以我将其修改为以下代码:

template<typename T>
class VectorDeque
{
private:
enum STORAGE_CONTAINER { NONE, DEQUE, VECTOR };
std::deque<std::deque<T> > x_d,y_d,z_d;
std::vector<std::vector<T> > x_v,y_v,z_v;
TYPE my_container;
public:
void resize(size_t num_atoms, size_t num_frames)
{
switch(m_type)
{
case NONE:
try
{
x_v.resize(num_atoms);
for (unsigned int couter=0;couter < num_frames; counter++)
x_v[counter].resize(num_frames);
y_v.resize(num_atoms);
for (unsigned int couter=0;couter < num_frames; counter++)
y_v[counter].resize(num_frames);
z_v.resize(num_atoms);
for (unsigned int couter=0;couter < num_frames; counter++)
z_v[counter].resize(num_frames);
my_container = VECTOR;
}
catch(std::bad_alloc &e)
{
x_d.resize(num_atoms);
for (unsigned int couter=0;couter < num_frames; counter++)
x_d[counter].resize(num_frames);
y_d.resize(num_atoms);
for (unsigned int couter=0;couter < num_frames; counter++)
y_d[counter].resize(num_frames);
z_d.resize(num_atoms);
for (unsigned int couter=0;couter < num_frames; counter++)
z_d[counter].resize(num_frames);
my_container = DEQUE;
}
break;
}
}
};

我现在希望能够定义我的括号运算符,这样我就可以有一个像这样的语句x[1][2] 直接访问我正在使用的真实 内存容器(由我的枚举变量的值给出。

我看过一些关于重写括号运算符的教程,但完全不知道重写双括号。

如何重载双括号?

此外,您将如何重载双迭代器(如果我想使用迭代器,而不是直接索引)?

编辑 1:

基于 Martin York/Matteo Italia 的解决方案,我设计了以下类:

template<typename T>
class VectorDeque2D
{
public:

class VectorDeque2D_Inner_Set
{
VectorDeque2D& parent;
int first_index;
public:
// Just init the temp object
VectorDeque2D_Inner_Set(My2D& p, int first_Index) :
parent(p),
first_Index(first_index) {}
// Here we get the value.
T& operator[](int second_index) const
{ return parent.get(first_index,second_index);}
};

// Return an object that defines its own operator[] that will access the data.
// The temp object is very trivial and just allows access to the data via
// operator[]
VectorDeque2D_Inner_Set operator[](unsigned int first_index) {
return (*this, x);
}


void resize_first_index(unsigned int first_index) {
try {
my_vector.resize(first_index);
my_container = VECTOR;
}
catch(std::bad_alloc &e) {
my_deque.resize(first_index);
my_container = DEQUE;
}
}

void resize_second_index(unsigned int second_index) {
try {
for (unsigned int couter=0;couter < my_vector.size(); counter++) {
my_vector[counter].resize(second_index);
}
my_container = VECTOR;
}
catch(std::bad_alloc &e) {
for (unsigned int couter=0;couter < my_deque.size(); counter++) {
my_deque[counter].resize(second_index);
}
my_container = DEQUE;
}
}
void resize(unsigned int first_index,
unsigned int second_index) {
try {
my_vector.resize(first_index);
for (unsigned int couter=0;couter < my_vector.size(); counter++) {
my_vector[counter].resize(second_index);
}
my_container = VECTOR;
}
catch(std::bad_alloc &e) {
my_deque.resize(first_index);
for (unsigned int couter=0;couter < my_deque.size(); counter++) {
my_deque[counter].resize(second_index);
}
my_container = DEQUE;
}
}
private:
enum STORAGE_CONTAINER { NONE, DEQUE, VECTOR };

friend class VectorDeque2D_Inner_Set;

std::vector<std::vector<T> > my_vector;
std::deque<std::deque<T> > my_deque;
STORAGE_CONTAINER my_container;

T& get(int x,int y) {
T temp_val;
if(my_container == VECTOR) {
temp_val = my_vector[first_index][second_index];
}
else if(my_container == DEQUE) {
temp_val = my_deque[first_index][second_index];
}

return temp_val;
}

};

终于有了大小安全的 2D 容器!!谢谢大家!

最佳答案

主要有两种技术:

1) 使用 operator() 而不是 operator[]。
这是因为 operator() 允许多个参数。

class My2D
{
public:
int& operator()(int x,int y) { return pget(x,y);}
private:
int& pget(int x,int y) { /* retrieve data from 2D storage */ }
};

2) 使用 operator[] 但返回一个中间对象。
然后,您可以将第二个运算符 [] 应用于中间对象。

class My2D
{
public:
class My2DRow
{
My2D& parent;
int x;
public:
My2DRow(My2D& p, int theX) : parent(p), x(theX) {} // Just init the temp object
int& operator[](int y) const { return parent.pget(x,y);} // Here we get the value.
};

// Return an object that defines its own operator[] that will access the data.
// The temp object is very trivial and just allows access to the data via operator[]
My2DRow operator[](int x) { return My2DRow(*this, x);}
private:
friend class My2DRow;
int& pget(int x,int y) { /* retrieve data from 2D storage */ }
};

int main()
{
My2D data;
int& val = data[1][2]; // works fine.

// This is the same as
My2D::My2DRow row = data[1];
int& val2 = row[2];
}

我更喜欢第二种技术。
这是因为它使原始代码保持不变并且更自然地阅读(在数组上下文中)。当然,您需要为实现 2D 数组的稍微复杂的代码在高层次上的简单性付出代价。

关于c++ - 如何定义双括号/双迭代器运算符,类似于 Vector of Vectors'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3755111/

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