我正在编写一个带有联合的通用短向量类来进行类型惩罚,所以我可以调整组件。例如,如果我声明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的目的。