类型特征相对于静态成员的优势
Advantages of type traits vs static members?
我有一个类(Voxel
),其子类可能有也可能没有许多不同的属性(材料,密度等),具有get和set方法。现在,我想编写如下代码:
template <typename VoxelType>
void process(VoxelType voxel)
{
if(VOXEL_HAS_MATERIAL)
{
//Do some work which involves calling get/setMaterial()
}
if(VOXEL_HAS_DENSITY)
{
//Do some work which involves calling get/setDensity()
}
}
因此,我想实现VOXEL_HAS_MATERIAL
和VOXEL_HAS_DENSITY
部分。两个简单的选项是:
- 在
Voxel
类中添加静态hasMaterial()
和hasDensity()
方法,以便在派生类中重写。 - 用
hasMaterial()
和hasDensity()
创建一个类型特征类,并为每个Voxel
子类特殊化。
使用method(2)允许为基本类型(int等)定义特征,但这在我的情况下没有用。在这里使用类型特征还有什么好处吗?或者我应该使用更简单的静态方法吗?
注意:我也知道基于SFINAE的方法,我将单独考虑。
Edit1:我已经更改了示例代码以显示模板的使用。我正在寻找这个问题的静态而不是运行时解决方案。理想情况下,如果编译器确定if语句不能针对给定类型执行,它将能够剥离if语句中的代码。
为什么这些方法应该是静态的?只需在Voxel类中声明virtual bool hasMaterial();
和virtual bool hasDensity();
方法,并在任何子类中重写它们。在子类中,如果有则返回true,如果没有则返回false。
你可以这样做:
void process(Voxel* voxel)
{
if(voxel->hasMaterial())
{
//Do some work which involves calling get/setMaterial()
}
if(voxel->hasDensity())
{
//Do some work which involves calling get/setDensity()
}
}
然后,你可以创建一个接口类的getter和setter的材料和密度,也让他们继承。
type -traits很有用,因为它们可以很容易地添加到类型中,即使你不能改变类型本身。此外,使用类型特征,您可以简单地提供一个合理的默认值(例如,您可以将hasMaterial
和hasDensity
委托给类的适当静态成员),然后您只需要为不使用此默认值的类专门化trait。
静态成员不能被重写。你应该让它们变成虚拟的。我猜你有设计的问题,请如果可能粘贴一些uml图或你的源代码。
使用静态检查代替运行时检查。
首先,定义这个宏:#define HAS_MEMBER_VARIABLE( NEW_STRUCT, VAR )
template<typename T> struct NEW_STRUCT {
struct Fallback { int VAR; }; /* introduce member name "VAR" */
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::VAR>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
检查类中是否存在成员变量。
如果变量存在,则使用SFINAE执行一些操作,如下面的示例:
#include <iostream>
#define HAS_MEMBER_VARIABLE( NEW_STRUCT, VAR )
template<typename T> struct NEW_STRUCT {
struct Fallback { int VAR; }; /* introduce member name "VAR" */
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::VAR>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
HAS_MEMBER_VARIABLE( x_check, x )
struct A
{
int x;
};
struct B
{
float notX;
};
template< typename T, bool hasX = x_check<T>::value >
struct doX
{
static void foo( const T & t )
{
std::cout<<"type has x variable, and it's value is "<<t.x<<std::endl;
}
};
template< typename T >
struct doX< T, false >
{
static void foo( const T & )
{
std::cout<<"type has no x variable"<<std::endl;
}
};
template< typename T >
void doFoo( const T& t )
{
doX< T, x_check<T>::value >::foo( t );
};
int main()
{
A a; a.x = 6;
B b; b.notX = 3.6;
std::cout<<"Calling foo() on A : ";
doFoo( a );
std::cout<<"Calling foo() on B : ";
doFoo( b );
}
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 如何在C++中使用非静态成员函数作为回调函数
- (C++)为什么静态成员可以在初始化之前使用
- 类的全局对象和静态成员
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- 模板化类中静态成员的延迟初始化
- 使用静态成员声明类时遇到问题
- C++:是否可以使用非静态成员变量模板?
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 如何在复杂继承中访问静态成员变量
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- C++构造函数和静态成员
- 为什么传递非静态成员函数会导致编译错误?
- 非静态成员失败的线程调用函数
- 静态成员变量不会由 gettext 转换
- decltype:使用指针访问类的静态成员
- 处理类内的回调时,必须调用对非静态成员函数的引用
- 特征中静态成员的初始化
- 类型特征相对于静态成员的优势