使用VS2015上的CRTP隐式删除默认构造函数,但不使用GCC或Clang

时间:2016-02-29 07:37:22

标签: c++11 gcc visual-studio-2015 clang default-constructor

我正在编写一个带有联合的通用短向量类来进行类型惩罚,所以我可以调整组件。例如,如果我声明Vector3 v3。我可以访问v3.yz作为Vector2。下面的代码可以很好地用GCC 4.8和-std = c ++ 11(或c ++ 1y)以及任何版本的Clang随Xcode 7.1一起使用。

但是,它不能使用msvc或Clang 3.7工具包在Visual Studio 2015上使用更新1进行编译:

#include <cstdint>
#include <cstdio>

template< int d, typename T, typename Derived >
class VectorBase
{
public:

    VectorBase()
    {
        for( int i = 0; i < d; ++i )
        {
            ( *this )[ i ] = T( 0 );
        }
    }

    const T& operator [] ( int i ) const
    {
        return static_cast< const Derived* >( this )->elements[ i ];
    }

    T& operator [] ( int i )
    {
        return static_cast< Derived* >( this )->elements[ i ];
    }
};

template< typename T >
class Vector2 : public VectorBase< 2, T, Vector2< T > >
{
public:

    typedef VectorBase< 2, T, Vector2 > Base;
    using Base::Base;

    union
    {
        struct
        {
            T x;
            T y;
        };
        T elements[ 2 ];
    };
};

template< typename T >
class Vector3 : public VectorBase< 3, T, Vector3< T > >
{
public:

    typedef VectorBase< 3, T, Vector3 > Base;
    using Base::Base;

    union
    {
        struct
        {
            T x;
            T y;
            T z;
        };
        struct
        {
            Vector2< T > xy;
        };
        struct
        {
            float __padding0;
            Vector2< T > yz;
        };
        T elements[ 3 ];
    };
};

int main( int argc, char* argv[] )
{
    Vector2< float > v2;
    Vector3< float > v3;

    printf( "v2 has size %zu, .x = %f, .y = %f\n", sizeof( v2 ), v2.x, v2.y );
    printf( "v3 has size %zu, .x = %f, .y = %f, .z = %f\n", sizeof( v3 ), v3.x, v3.y, v3.z );
}

VS 2015抱怨错误消息:

1>  main.cpp
1>main.cpp(79,22): error : call to implicitly-deleted default constructor of 'Vector3<float>'
1>      Vector3< float > v3;
1>                       ^
1>  main.cpp(63,9) :  note: default constructor of 'Vector3<float>' is implicitly deleted because variant field '' has a non-trivial default constructor
1>          struct
1>          ^
1>  1 error generated.

编译器认为默认构造函数是非常重要的并隐式删除它是有道理的。没有意义的是为什么继承使用声明的构造函数失败,以及编译器之间的区别。

我可以通过显式添加一个在初始化列表中显式调用VectorBase构造函数的Vector3构造函数来使其工作,但这有点违背了使用CRTP的目的。

0 个答案:

没有答案