类型特征相对于静态成员的优势

Advantages of type traits vs static members?

本文关键字:静态成员 特征 相对于 类型      更新时间:2023-10-16

我有一个类(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_MATERIALVOXEL_HAS_DENSITY部分。两个简单的选项是:

  1. Voxel类中添加静态hasMaterial()hasDensity()方法,以便在派生类中重写。
  2. 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很有用,因为它们可以很容易地添加到类型中,即使你不能改变类型本身。此外,使用类型特征,您可以简单地提供一个合理的默认值(例如,您可以将hasMaterialhasDensity委托给类的适当静态成员),然后您只需要为不使用此默认值的类专门化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 );
}