2014-10-20 50 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

相關問題