2012-06-15 45 views
26

我正在構建一些輸入檢查器,它需要具有整數和/或雙精度的特定函數(例如'isPrime'應該只能用於整數)。std :: enable_if:參數vs模板參數

如果我使用enable_if作爲參數,它的工作完美:

template <class T> 
class check 
{ 
public: 
    template< class U = T> 
    inline static U readVal(typename std::enable_if<std::is_same<U, int>::value >::type* = 0) 
    { 
     return BuffCheck.getInt(); 
    } 

    template< class U = T> 
    inline static U readVal(typename std::enable_if<std::is_same<U, double>::value >::type* = 0) 
    { 
     return BuffCheck.getDouble(); 
    } 
}; 

,但如果我使用它作爲一個模板paramater(如表現出對http://en.cppreference.com/w/cpp/types/enable_if

template <class T> 
class check 
{ 
public: 
    template< class U = T, class = typename std::enable_if<std::is_same<U, int>::value>::type > 
    inline static U readVal() 
    { 
     return BuffCheck.getInt(); 
    } 

    template< class U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type > 
    inline static U readVal() 
    { 
     return BuffCheck.getDouble(); 
    } 
}; 

然後我有以下錯誤:

error: ‘template<class T> template<class U, class> static U check::readVal()’ cannot be overloaded 
error: with ‘template<class T> template<class U, class> static U check::readVal()’ 

我不能數字o在第二個版本中出了什麼問題。

+0

可能無關緊要,但在VS2010我不能這樣做,因爲默認模板參數只允許類模板 - 我不知道G ++ – David

+2

這是迂腐,但'inline'關鍵字上一個成員方法或模板是不需要的,當然不是一個也是模板的成員;-) – AJG85

回答

31

默認模板參數不是模板簽名的一部分(所以兩個定義都嘗試兩次定義相同的模板)。然而,它們的參數類型是簽名的一部分。所以,你可以做

template <class T> 
class check 
{ 
public: 
    template< class U = T, 
      typename std::enable_if<std::is_same<U, int>::value, int>::type = 0> 
    inline static U readVal() 
    { 
     return BuffCheck.getInt(); 
    } 

    template< class U = T, 
      typename std::enable_if<std::is_same<U, double>::value, int>::type = 0> 
    inline static U readVal() 
    { 
     return BuffCheck.getDouble(); 
    } 
}; 
+1

+1,我認爲這看起來比其他方法更清潔。 – ildjarn

+0

非常聰明的解決方案! – plasmacel

+1

因此,默認類型模板參數(具有默認類型)不是模板簽名的一部分,而是默認的非類型模板參數(具有默認常量整數值)。那是對的嗎? – Alan

7

問題是,編譯器會看到同一個方法的兩個重載,它們都包含相同的參數(在本例中爲none)和相同的返回值。你不能提供這樣的定義。最簡單的方法是在函數的返回值上使用SFINAE:

template <class T> 
class check 
{ 
public: 
    template< class U = T> 
    static typename std::enable_if<std::is_same<U, int>::value, U>::type readVal() 
    { 
     return BuffCheck.getInt(); 
    } 

    template< class U = T> 
    static typename std::enable_if<std::is_same<U, double>::value, U>::type readVal() 
    { 
     return BuffCheck.getDouble(); 
    } 
}; 

這樣,您就提供了2種不同的重載。一個返回一個int,另一個返回一個double,並且只有一個可以使用特定的T實例化。