【问题标题】:Vector, proxy class and dot operator in C++C++ 中的向量、代理类和点运算符
【发布时间】:2011-08-24 22:14:04
【问题描述】:

一个与 C++ 中的自定义 Vector 类相关的问题。

template <typename T>
class Vector
{ ...
  private:
    T * mData; int mSize;
  public:
    proxy_element operator[](const size_type index) { return proxy_element(*this, index); }
    const T& operator[](const size_type index) const {   return mData[index]; }
};

template <typename T>
class proxy_element
{  ...
   proxy_element(Vector<T>& m_parent, const size_type index);
   proxy_elem& operator=(const T& rhs); // modifies data so invalidate on other memories
   bool operator==(const proxy_elem& rhs) // only read, just copy data back.
   ...
}

使用proxy_element类的原因是为了区分和优化读写操作,考虑到向量数据也可以驻留在GPU设备内存中。因此,任何读取操作只需要将最新数据复制回来(如果有的话),但读写操作需要使设备内存中的数据无效。

当元素类型是原始的时,这种设计效果很好。但是对于更复杂的元素类型,存在一个问题:

struct person{ int age; double salary; }; 
int main()
{
   Vector<person> v1(10); 
   v[1].age = 10; // gives error as operator[] returns proxy_element for which "." operator has no meaning
}

AFAIK,“。”运算符在 C++ 中不能重载。一个明显的解决方案是不使用 proxy_elem 而只返回常规引用 (T &),假设每次访问都是写访问,但由于显而易见的原因,这将是低效的。

是否有任何其他工作可以让我“。”操作员在工作的同时保留区分读写操作的能力?

【问题讨论】:

  • 在更复杂类型的情况下是否可以使用指针?然后你也许可以通过重载 operator->. 来解决你的问题
  • @TeaWolf:谢谢。我知道该选项,但正在寻找使其适用于常规类型。

标签: c++ vector gpu


【解决方案1】:

一种选择是使此类数据类型不可变(私有成员变量,由构造函数初始化,唯一的设置器是类的赋值运算符)。这样,更改任何内容的唯一方法就是分配给类的整个实例,该实例可以通过 proxy_element 进行引导。

【讨论】:

  • 谢谢,但是如果您无法控制元素类型怎么办?因为我有兴趣拥有一个通用解决方案而不限制元素类型。但正如你所说,这显然是不可能的。
【解决方案2】:

Marcelo Cantos 的回答当然是正确的做事方式。但是,专业化有复杂而疯狂的解决方法。 (不推荐。)

//if it's a class, inherit from it to get public members
template<class T> 
class proxy_element : public T {
    ...
    proxy_element(Vector<T>& m_parent, const size_type index);
    proxy_elem& operator=(const T& rhs); // modifies data so invalidate on other memories
    bool operator==(const proxy_elem& rhs) // only read, just copy data back.
    ...
};
//pretend to be a pointer
template<> 
class proxy_element<T*> {
    ...
    proxy_element(Vector<T>& m_parent, const size_type index);
    proxy_elem& operator=(const T& rhs); // modifies data so invalidate on other memories
    bool operator==(const proxy_elem& rhs) // only read, just copy data back.
    ...
};
//otherwise, pretend to be primitive
#define primitive_proxy(T) \
template<> class proxy_element {
    ...
    proxy_element(Vector<T>& m_parent, const size_type index);
    proxy_elem& operator=(const T& rhs); // modifies data so invalidate on other memories
    bool operator==(const proxy_elem& rhs) // only read, just copy data back.
    ...
};
primitive_proxy(char)
primitive_proxy(unsigned char)
primitive_proxy(signed char) //this is distinct from char remember
primitive_proxy(short)
primitive_proxy(unsigned short)
primitive_proxy(int)
primitive_proxy(unsigned int)
primitive_proxy(long)
primitive_proxy(unsigned long)
primitive_proxy(long long)
primitive_proxy(unsigned long long)
primitive_proxy(char16_t) //if GCC
primitive_proxy(char32_t) //if GCC
primitive_proxy(wchar_t)
primitive_proxy(float)
primitive_proxy(double)
primitive_proxy(long double)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-07
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多