派生类中的成员字段别名(无访问器功能)

Member field aliases in derived class (no accessor functions)

本文关键字:访问 功能 别名 成员 字段 派生      更新时间:2023-10-16

玩具示例:

template<typename T, std::size_t N>
class static_vector
{
public:
    T& operator[](std::size_t i) { return m_elements[i]; }
    T const& operator[](std::size_t i) const { return m_elements[i]; }
private:
    std::array<T, N> m_elements;
};
template<typename T>
class vector3
    : public static_vector<T, 3>
{
public:
    using vector_type = static_vector<T, 3>;
//  x = vector_type::operator[](0);
//  y = vector_type::operator[](1);
//  z = vector_type::operator[](2);
};

vector3<float> pos;。我想通过pos.x访问pos[0]。显然,如果宣布posconst,我希望pos.x仅阅读。

这是可能的吗?

让我强调一个事实,我不想使用表单的访问器功能

T& x() { return (*this)[0]; }
T const& x() const { return (*this)[0]; }

使用您想要的确切语法没有零成本的方式。

放松成本(编译,维护,内存使用时间和运行时(或语法(您的()是一个示例(可以带您想要的东西。

我在您的问题中添加了评论,但我想我会添加一个带有一些代码的答案以澄清。请警告,接下来是一个好主意。

您可以使用简单的指针算术来解释struct的成员,就像它们是array中的元素一样。因为struct成员的类型和伪array中的元素类型是相同的,所以我们可以安全地重新诠释一个,因为另一个 waveat struct成员之间没有填充。

C 标准没有定义struct中填充的方法,因此您必须依靠编译器特定指令。但是我相信MSVC和GCC都支持#pragma pack

#pragma pack(push, 1)
template <typename T>
struct Vec3
{
    T x;
    T y;
    T z;
    T& operator[](size_t i) { return *(&x + i); }
    const T& operator[](size_t i) const { return *(&x + i); }
};
#pragma pack(pop)

那么为什么这不是一个很好的解决方案?

  • 您依靠编译器特定指令,使您的代码降低了便携式。

  • 您需要明确声明每个成员,这意味着您需要用于VEC2,VEC3和VEC4的单独模板。

  • 1个字节对齐不支持所有架构,使您的代码降低了便携式。

  • 即使在支持未对齐的内存访问(例如x86(的体系结构上,也会带有性能惩罚。