2010-03-29 114 views
7

考慮下面的例子:如何爲具有特定類型特徵的所有類型編寫函數模板?

struct Scanner 
{ 
    template <typename T> 
    T get(); 
}; 

template <> 
string Scanner::get() 
{ 
    return string("string"); 
} 

template <> 
int Scanner::get() 
{ 
    return 10; 
} 

int main() 
{ 
    Scanner scanner; 
    string s = scanner.get<string>(); 
    int i = scanner.get<int>(); 
} 

Scanner類用於提取一些源令牌。上面的代碼工作正常,但當我嘗試get其他整數類型時,如charunsigned int失敗。讀取這些類型的代碼與讀取int的代碼完全相同。我可以複製所有其他我想閱讀的整型類型的代碼,但我寧願爲所有整型類型定義一個函數模板。

我已經試過如下:

struct Scanner 
{ 
    template <typename T> 
    typename enable_if<boost::is_integral<T>, T>::type get(); 
}; 

這就像一個魅力,但我不確定如何讓Scanner::get<string>()再次發揮作用。那麼,我如何編寫代碼,以便我可以執行scanner.get<string>()scanner.get<any integral type>()並且具有單個定義來讀取所有整型?

更新:獎金問題:如果我想根據某些特徵接受一個以上的班級範圍,該怎麼辦?例如:如果我想要有三個get函數分別接受(i)整數類型(ii)浮點類型(iii)字符串,我該如何處理這個問題。

回答

10
struct Scanner 
{ 
    template <typename T> 
    typename boost::enable_if<boost::is_integral<T>, T>::type get() 
    { 
     return 10; 
    } 
    template <typename T> 
    typename boost::disable_if<boost::is_integral<T>, std::string>::type get() 
    { 
     return "string"; 
    } 
}; 

更新

struct Scanner 
{ 
    template <typename T> 
    typename boost::enable_if<boost::is_integral<T>, T>::type get() 
    { 
     return 10; 
    } 

    template <typename T> 
    typename boost::enable_if<boost::is_floating_point<T>, T>::type get() 
    { 
     return 11.5; 
    } 

    template <typename T> 
    std::string get(
      typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0, 
      typename boost::disable_if<boost::is_integral<T>, T>::type* = 0) 

    { 
     return std::string("string"); 
    } 
}; 
+2

我會說,你可以使用'boost :: mpl :: and_'和'boost :: mpl :: or_'來結合'disable_if'中的參數。 +1儘管如此:) – 2010-03-29 12:54:43

+0

您也可以使用Boost庫中的'ice_and'和'ice_or'。 – 2010-03-29 14:02:01

3

推遲到另一個模板。這裏有你想要的東西的一般模式:「如果我想接受基於一些traits類以上的範圍是什麼」

template <typename T, bool HasTrait = false> 
struct scanner_impl; 

template <typename T> 
struct scanner_impl 
{ 
    // Implement as though the trait is false 
}; 

template <typename T> 
struct scanner_impl<true> 
{ 
    // Implement as though the trait is true 
}; 

// This is the one the user uses 
template <typename T> 
struct scanner : scanner_impl<T, typename has_my_trait<T>::value> 
{ 
}; 
+1

好主意以這種方式增加間接性。如果你不使用'bool',而是使用'enum'作爲trait-switch,可能會變得更加靈活。 – xtofl 2010-03-29 11:56:12

+0

@xtofl:是的。這也會回答獎金問題。 – 2010-03-29 14:00:13

相關問題