将联合体的变量公开为类成员变量[重复]

问题描述 投票:0回答:1

我已经得到了刚刚成功编译的代码:

template <typename T, unsigned int N>
struct Vector
{
    struct Vec1
    {
        T x;
    };

    struct Vec2 : public Vec1
    {
        T y;
    };

    struct Vec3 : public Vec2
    {
        T z;
    };

    struct Vec4 : public Vec3
    {
        T w;
    };

    template <unsigned int N>
    union Data
    {
        std::array<T, N> components;
    };

    template <>
    union Data<1>
    {
        Vec1 vec;
        std::array<T, 1> components;
    };

    template <>
    union Data<2>
    {
        Vec2 vec;
        std::array<T, 2> components;
    };

    template <>
    union Data<3>
    {
        Vec3 vec;
        std::array<T, 3> components;
    };

    template <>
    union Data<4>
    {
        Vec4 vec;
        std::array<T, 4> components;
    };

    Data<N> data;
};

它按预期工作,但是我希望结构

Vector
将数据的变量公开为其自己的成员变量。

可以吗?

解决方案将允许我做

Vector<int, 3> vec; vec.x ...; vec.components[0] ...;

联合的目的是轻松地以数组和单独方式访问向量的组件。

另外,如果您碰巧知道更好的方法来实现模板化联合

Data
专业化,请说出来,因为我发现它有点硬编码。如果能够递归地添加变量,而无需添加之前特化的变量,那就太完美了。

例如,我只需要声明一次

T x

c++ templates unions
1个回答
5
投票

我认为你需要让你的设计和代码更加清晰。

使用

template <>
union Data<3>
{
    T x;
    T y;
    T z;
    std::array<T, 3> components;
};

听起来不对。您需要有

{x, y, z}
components
,而不是
x
、或
y
、或
z
、或
components
。你需要的是类似的东西

template <>
union Data<3>
{
    struct
    {
       T x;
       T y;
       T z;
    } members;
    std::array<T, 3> components;
};

话虽如此,最干净的成员变量就是

    std::array<T, N> components;

就成员变量而言,

Vector
可以定义为:

template <typename T, unsigned int N>
struct Vector
{
   std::array<T, N> components;
};

如果需要通过

components
x
y
之类的抽象来公开
z
的元素,最好添加成员函数。

template <typename T, unsigned int N>
struct Vector
{
   std::array<T, N> components;

   T& x()
   {
      static_assert(N > 0);
      return components[0];
   }

   T& y()
   {
      static_assert(N > 1);
      return components[1];
   }

   T& z()
   {
      static_assert(N > 2);
      return components[2];
   }
};

根据上述

Vector
的定义,以下
main
函数应该可以工作。

int main()
{
   Vector<int, 1> v1;
   v1.x() = 20;

   Vector<int, 2> v2;
   v2.x() = 20;
   v2.y() = 30;

   Vector<int, 3> v3;
   v3.x() = 20;
   v3.y() = 30;
   v3.z() = 40;
}

如果您使用

   Vector<int, 2> v2;
   v2.z() = 20;

你应该得到一个编译时错误。

您可以添加上述函数的

const
版本,以使成员函数也可以与
const
对象一起使用。

template <typename T, unsigned int N>
struct Vector
{
   std::array<T, N> components;

   T& x()
   {
      static_assert(N > 0);
      return components[0];
   }

   T const& x() const
   {
      static_assert(N > 0);
      return components[0];
   }

   T& y()
   {
      static_assert(N > 1);
      return components[1];
   }

   T const& y() const
   {
      static_assert(N > 1);
      return components[1];
   }

   T& z()
   {
      static_assert(N > 2);
      return components[2];
   }

   T const& z() const
   {
      static_assert(N > 2);
      return components[2];
   }
};
© www.soinside.com 2019 - 2024. All rights reserved.