2014-10-20 49 views
1

所以我有这个模板函数。 它应该设置一个变量在一个名为AbstractEvent更复杂的结构:模板函数实现中的条件取决于类型是否是指针

template< typename T > 

void AbstractEvent::setVar(QString varName, T value) 
{ 
    if (std::is_pointer<T>::value) 
    { 
     void * castValue = static_cast<void*>(value); 
     if (castValue) 
     { 
      //do sth with castValue 
     } 

    } 
    else 
    { 
     //do something with value 
    } 
} 

有了这个模板的功能,我想存储在一个的QVariant变量“值”,然后保存的QVariant地方。

如果“value”是一个指针,我想将它作为void *存储在QVariant中。对于其他任何我想存储真实类型的东西。

我试着用C++ trait std :: is_pointer :: value来检查值是否是一个指针。

此代码编译罚款,但是当我尝试使用它,用,例如:

int intValue = 0; 
setVar<int>("aVar",intValue); 

我得到这个错误:

error C2440: 'static_cast' : unable to convert from 'int' to 'void *' 

我觉得编译器是困惑,因为它的检查这一行:

void * castValue = static_cast<void*>(value); 

当然,当值不是指针时,它当然没有意义。这就是我的if语句

 if (std::is_pointer<T>::value) 

应该避免的,但是,即使在运行时,这段代码以价值为int将永远不会被执行,在编译时它混淆编译器是...有没有解决这类问题的方法?

回答

5

标签调度:

template< typename T > 
void AbstractEvent::setVar_impl(QString varName, T value, std::true_type /*is_ptr*/) 
{ 
    void * castValue = static_cast<void*>(value); 
    if (castValue) 
    { 
      //do sth with castValue 
    } 
} 

template< typename T > 
void AbstractEvent::setVar_impl(QString varName, T value, std::false_type /*is_ptr*/) 
{ 
    //do something with value 
} 

template< typename T > 
void AbstractEvent::setVar(QString varName, T value){ 
    setVar_impl(varName, value, std::is_pointer<T>()); 
} 

备选地,过载,然后SFINAE出不适用的一个:

template<typename T> 
typename std::enable_if<std::is_pointer<T>::value>::type 
AbstractEvent::setVar(QString varName, T value) 
{ 
    void * castValue = static_cast<void*>(value); 
    if (castValue) 
    { 
      //do sth with castValue 
    } 
} 

template< typename T> 
typename std::enable_if<!std::is_pointer<T>::value>::type 
AbstractEvent::setVar(QString varName, T value) 
{ 
    //do something with value 
} 

第三替代方案中,过载直接:

template< typename T > 
void AbstractEvent::setVar(QString varName, T* value) 
{ 
    void * castValue = static_cast<void*>(value); 
    if (castValue) 
    { 
      //do sth with castValue 
    } 
} 

template< typename T > 
void AbstractEvent::setVar(QString varName, T value) 
{ 
    //do something with value 
} 

第一个模板是更专业比第二部分偏序,所以如果两者同样可行,将被选择。

您可能还想特例T == nullptr_t的情况。 nullptr_t不是指针类型,但您可能希望在该情况下调用指针超载。

3

您也可以坚持自己的设计通过使用std::conditional

typedef typename std::conditional<std::is_pointer<T>::value, void*, T>::type cast_type; 
auto castValue = static_cast<cast_type>(value); 

但是,使用tag分派或超载的解决方案 - 尽管长 - 是也许有点清晰。

4

简单的重载,任何人?

template<typename T> 
void AbstractEvent::setVar(QString varName, T value); 

template<typename T> 
void AbstractEvent::setVar(QString varName, T* value); 
+1

我需要开始参加Complexity Anonymous。 – 2014-10-20 13:45:52

相关问题