【问题标题】:Clang complains that a POD class is actually non-PODClang 抱怨 POD 类实际上是非 POD
【发布时间】:2023-03-04 21:28:01
【问题描述】:

更新:我已经修改了这里的代码,以便您可以直接插入并尝试编译。

当在可变参数函数中使用时,Clang 3.4.1 (LLVM 3.4) 抱怨我的类不是 POD 类型(据我所知,这是肯定的)。 G++ 编译这个没有问题。

即使按照 C++03 的标准,这个类也是 POD:

  • 它只包含 PODS 作为成员
  • 没有用户定义的析构函数
  • 没有用户定义的复制赋值运算符
  • 没有指向成员类型的非静态成员

C++11 对什么是“POD”的规则放宽了,那么这里发生了什么?

关于代码:这是一个向量的模板类(如在矢量图形中),可变参数函数仅用于用一些任意数据填充数组。

我的班级头文件:

template<typename TYPE>
class Vec3t;

typedef Vec3t<float> Vec3f;

template<typename TYPE>
class Vec3t {
public:
    Vec3t<TYPE>( void ){}
    Vec3t<TYPE>( const TYPE nx, const TYPE ny, const TYPE nz ){}

    Vec3t<TYPE> operator-(void) const{}

    Vec3t<TYPE> operator*( const Vec3t<TYPE> &other ) const{}
    Vec3t<TYPE> operator*( const TYPE val ) const{}
    Vec3t<TYPE>& operator*=( const Vec3t<TYPE> &other ){}
    Vec3t<TYPE>& operator*=( const TYPE val ){}

    Vec3t<TYPE> operator+( const Vec3t<TYPE> &other ) const{}
    Vec3t<TYPE> operator+( const TYPE val ) const{}
    Vec3t<TYPE>& operator+=( const Vec3t<TYPE> &other ){}
    Vec3t<TYPE>& operator+=( const TYPE val ){}

    Vec3t<TYPE> operator-( const Vec3t<TYPE> &other ) const{}
    Vec3t<TYPE> operator-( const TYPE val ) const{}
    Vec3t<TYPE>& operator-=( const Vec3t<TYPE> &other ){}
    Vec3t<TYPE>& operator-=( const TYPE val ){}

    Vec3t<TYPE> operator/( const Vec3t<TYPE> &other ) const{}
    Vec3t<TYPE> operator/( const TYPE val ) const{}
    Vec3t<TYPE>& operator/=( const TYPE val ){}
    Vec3t<TYPE>& operator/=( const Vec3t<TYPE> &other ){}

    bool operator==( const Vec3t<TYPE> &b ) const {}
    bool operator==( const TYPE b ) const {}
    bool operator!=( const Vec3t<TYPE> &b ) const {}
    bool operator!=( const TYPE b ) const {}

    Vec3t<TYPE>& Set( const TYPE a, const TYPE b, const TYPE c ){}
    Vec3t<TYPE>& Set( const TYPE a, const TYPE b ){}

    void Cross( const Vec3t<TYPE> &other, Vec3t<TYPE> &out ) const{}

    TYPE Dot( const Vec3t<TYPE> &other ) const{}

    Vec3t<TYPE> PerpCCW_ZAxis( void ){}
    Vec3t<TYPE> PerpCW_ZAxis( void ){}

    float Len( void ) const{}
    void Zero( void ){}

    static void Cross( const Vec3t<TYPE> &other, const Vec3t<TYPE> &u, Vec3t<TYPE> &out ){}

    Vec3f Normalize( void ){}
    Vec3f Rotation( TYPE angle ){}
    float DegreesBetween( const Vec3f &other ){}
    float RadiansBetween( const Vec3f &other ){}
    Vec3f Rotate( float angle, const bool inRadians = false ){}
    static float Len( const Vec3f &other ){}

public:
    TYPE        x,y,z;
};

template< typename TYPE >
void FillArray( const std::size_t count, TYPE* var, ... ) {
    va_list vargs;
    va_start( vargs, var );

    for ( std::size_t i=0; i<count; i++ ) {
        var[i] = va_arg( vargs, TYPE ); // ** THIS IS THE LINE CLANG ERRS ON ** //
    }

    va_end( vargs );
}

我的可变参数函数头文件:

#include <cstdarg>

template< typename TYPE >
void FillArray( const std::size_t count, TYPE* var, ... ) {
    va_list vargs;
    va_start( vargs, var );

    for ( std::size_t i=0; i<count; i++ ) {
        var[i] = va_arg( vargs, TYPE ); // ** THIS IS THE LINE CLANG ERRS ON ** //
    }

    va_end( vargs );
}

Clang 的错误: 错误:“va_arg”的第二个参数是非 POD 类型“Vec3t”[-Wnon-pod-varargs]

使用这些导致 Clang 错误的示例程序: #include "fillarray.h"

int main ( void ) {
    Vec3t<float> v[2];
    FillArray< Vec3t<float> >( 2, v, 0.4f, 0.5f);
}

编译: clang++ x.cpp -I/usr/include/i386-linux-gnu/c++/4.8 -std=gnu++11

【问题讨论】:

  • 为了调试这个(以及一个更简洁的问题),我建议尽可能多地从你的类定义中删除。
  • 奇怪的是它暗示Vec3t 是一个类型,而它实际上是一个模板。
  • 作为记录,我 typedef Vec3t 到 Vec3f。虽然我怀疑这有什么关系。
  • 如果你不确定一个类型是否是 POD,那么,将 static_assert 与 std::is_pod 一起使用。

标签: c++ c++11 clang llvm variadic-functions


【解决方案1】:

§12.1/7:

如果默认构造函数不是用户提供的并且......

否则,默认构造函数是非平凡的

根据定义,您声明的默认构造函数是不平凡的。

§9/3:

普通类是具有普通默认构造函数 (12.1) 且可轻松复制的类。

由于默认构造函数是不平凡的,类是不平凡的。

§9/10:

POD 结构是一个非联合类,它既是普通类又是标准布局类...

由于该类不是微不足道的,因此它不符合 POD 的条件。为了使它成为 POD,你必须摆脱默认的构造函数。

【讨论】:

  • 是的,这就是问题所在。你是从哪里复制这些信息的?上次我听说实际 C++ ISO 标准的打印输出或 PDF 需要花钱。我所能找到的只是用谷歌搜索的随机花絮,通常在 Stack Overflow 上找到。
  • @zeroth:我有一份标准的副本。 ANSI、IIRC 的价格是 30 美元。
  • @zeroth:你可以随时免费获得工作草案,链接来自here
  • @zeroth 当您使用 C++11 时,您不需要摆脱默认构造函数。您可以使用“= default”语法使其变得简单。这允许您拥有其他非默认和非平凡的构造函数。见en.wikipedia.org/wiki/…
猜你喜欢
  • 1970-01-01
  • 2019-03-17
  • 2020-01-26
  • 2019-05-17
  • 1970-01-01
  • 2013-01-03
  • 1970-01-01
  • 2011-01-18
  • 2022-12-07
相关资源
最近更新 更多