如何防止无名结构\联合?

发布于 2024-12-26 19:08:55 字数 592 浏览 4 评论 0原文

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

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];
    };

(是的,我知道有可用的矩阵库。请不要将其变成“使用 xxx 库”讨论,我这样做是为了扩展我的 C++ 知识。)

I am building a class that has a union for its matrix data, however, I can only get it compile when I do not have a name for the struct\union. However, with a higher level warning level (four on visual studio) I will a warning saying

warning C4201: nonstandard extension used : nameless struct/union

I looked into it, and I don't seem to be able to find a way to prevent this. Anyway possible that I know of will cause a different compiler error related to the declaration of one or the other. How can I prevent getting this warning and make it conform to standards, without just disabling the warning.

    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];
    };

(Yes, I know there is matric libraries available. Please do not turn this into a "use xxx library" discussion, I am doing this to expand my knowledge of C++".)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

你列表最软的妹 2025-01-02 19:08:55

命名它似乎是最好的。 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


私人/公共(某种程度):

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];
  };
};

Naming it seems best. Anonymous unions are allowed in C++, just not structs.

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];
};

You can use references/macros to allow access without bar.

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

Essentially the same as an anonymous struct. I don't really recommend this though. Use bar._11 if possible.


Private/public (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];
  };
};
子栖 2025-01-02 19:08:55

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

#pragma warning(disable : 4201)

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

#pragma warning(default : 4201)

有关其他参考,请参阅 MSDN < href="http://msdn.microsoft.com/en-us/library/2c8f766e%28v=VS.100%29.aspx" rel="noreferrer">文档。

If all you want to do is to disable the warning without changing the actual code then you can use #pragma warning directive like so:

#pragma warning(disable : 4201)

If you want to reenable it again use:

#pragma warning(default : 4201)

For addition reference, see MSDN documentation.

蓝礼 2025-01-02 19:08:55
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];
};

我修复了它,没有给结构类命名,只是给实例名称。

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];
};

I fixed it without giving the struct class a name, just the instance name.

泅渡 2025-01-02 19:08:55

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

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()添加到类中来解决......但那是另一个故事了。

The most common way I have seen to address this is by overloading the array operator for the type. It is fairly specific to the example you posted, but similar methods can be used in other situations where a nameless struct seems like the only option.

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])); 
    }
};

But, where there is a matrix there are usually vectors, this can be used to your advantage by defining the array operator in the vector class similar to the array operator defined above. But instead of returning a reference to a F32 in the matrix array operator, return a reference to a vector. Here is an example:

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])); }
};

Now code can can be written much more naturally and is still efficient, for example:

 F32 m00 = mymat4[0][0];

or:

 vector4 col0 = mymat4[0];

The biggest drawback of this approach is that the matrix now has to be index [col][row]. This can be resolved by adding the operator() to the class...but thats another story.

北方。的韩爷 2025-01-02 19:08:55

您收到的警告不是关于内部结构的,而是关于联合本身的。试试这个:

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;

You have this warning not about the inner struct but about union itself. Try this:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文