如何防止无名的struct \ union?

时间:2012-01-13 04:24:52

标签: c++ struct standards unions

我正在构建一个具有矩阵数据联合的类,但是,当我没有struct \ union的名称时,我只能编译它。但是,如果有更高级别的警告级别(视觉工作室有四个),我会发出警告说

warning C4201: nonstandard extension used : nameless struct/union

我调查了一下,我似乎无法找到防止这种情况的方法。无论如何,我所知道的可能会导致与一个或另一个的声明相关的不同编译器错误。如何在不禁用警告的情况下阻止获取此警告并使其符合标准。

    union
    {
        struct
        {
            F32 _11, _12, _13, _14;
            F32 _21, _22, _23, _24;
            F32 _31, _32, _33, _34;
            F32 _41, _42, _43, _44;
        };
        F32 _m[16];
    };

(是的,我知道有可用的matric库。请不要将其转换为“使用xxx库”讨论,我这样做是为了扩展我对C ++的了解“。)

5 个答案:

答案 0 :(得分:6)

命名似乎最好。在C ++中允许使用匿名联合,而不是结构。

union
{
    struct foo
    {
        F32 _11, _12, _13, _14;
        F32 _21, _22, _23, _24;
        F32 _31, _32, _33, _34;
        F32 _41, _42, _43, _44;
    } bar;
    F32 _m[16];
};

您可以使用引用/宏来允许在没有bar的情况下进行访问。

F32& _11 = bar._11;
F32& _12 = bar._12;

基本上与匿名结构相同。我不是真的推荐这个。如果可能,请使用bar._11


私人/公共(sorta):

struct mat 
{
  struct foo 
  {
    friend class mat;
    private:
      F32 _11, _12, _13, _14;
      F32 _21, _22, _23, _24;
      F32 _31, _32, _33, _34;
      F32 _41, _42, _43, _44;
  };
  union
  {
    foo bar;
    F32 _m[16];
  };
};

答案 1 :(得分:3)

如果您只想在不更改实际代码的情况下禁用警告,那么您可以使用#pragma warning指令,如下所示:

#pragma warning(disable : 4201)

如果您想再次启用它,请使用:

#pragma warning(default : 4201)

有关其他参考,请参阅MSDN documentation

答案 2 :(得分:0)

union
{
    struct // <- not named here
    {
        F32 _11, _12, _13, _14;
        F32 _21, _22, _23, _24;
        F32 _31, _32, _33, _34;
        F32 _41, _42, _43, _44;
    } AsStruct; // <- named here
    F32 AsArray[16];
};

我修复了它,却没有给struct类一个名称,只是实例名称。

答案 3 :(得分:0)

我见过的最常见的解决方法是重载类型的数组运算符。它与您发布的示例相当具体,但类似的方法可用于其他情况,其中无名结构似乎是唯一的选择。

struct Mat {
   F32
    _11, _12, _13, _14,
    _21, _22, _23, _24,
    _31, _32, _33, _34,
    _41, _42, _43, _44;

  
    f32& operator[](uint32 ndx) { 
           return *reinterpret_cast<F32*>(&((&_11)[ndx])); 
     }
    const F32& operator[](uint32 ndx) const { 
           return *reinterpret_cast<const F32*>(&((&_11)[ndx])); 
    }
};

但是,在有矩阵的地方通常有向量,这可以通过在向量类中定义类似于上面定义的数组运算符的数组运算符来发挥你的优势。但不是返回对矩阵数组运算符中 F32 的引用,而是返回对向量的引用。下面是一个例子:

struct vector4{
    F32 x,y,z,w;
    f32& operator[](uint32 ndx) { 
       return *reinterpret_cast<F32*>(&((&x)[ndx])); 
    }
    const F32& operator[](uint32 ndx) const { 
       return *reinterpret_cast<const F32*>(&((&x)[ndx])); 
    }
};

struct matrix4 {
    
   F32
    _11, _12, _13, _14,
    _21, _22, _23, _24,
    _31, _32, _33, _34,
    _41, _42, _43, _44;


    vector4& operator[](uint32 ndx) { return *reinterpret_cast<vector4*>(&((&_11)[ndx * 4])); }
    const vector4& operator[](uint32 ndx) const { return *reinterpret_cast<const vector4*>(&((&_11)[ndx * 4])); }
};

现在可以更自然地编写代码并且仍然高效,例如:

 F32 m00 = mymat4[0][0];

或:

 vector4 col0 = mymat4[0];

这种方法的最大缺点是矩阵现在必须是索引 [col][row]。这可以通过将 operator() 添加到类中来解决...但那是另一回事了。

答案 4 :(得分:-1)

你有这个警告不是关于内部结构而是关于联合本身。试试这个:

union Mat    // <-------
{
    struct
    {
        F32 _11, _12, _13, _14;
        F32 _21, _22, _23, _24;
        F32 _31, _32, _33, _34;
        F32 _41, _42, _43, _44;
    };
    F32 _m[16];
};

Mat mat;
mat._11 = 42;
F32 x = mat._22;
mat._m[ 3 ] = mat._33;