簡體   English   中英

一組類型的模板特化

[英]Template specialization for a set of types

如何為一組數據類型專門設計一個模板? 例如:

template<typename T>
inline T getRatio(T numer, T denom){
    return (numer/denom);
}

我想將它專門用於一組數據類型,因此它僅適用於intlongdoublefloat 因此,如果用戶嘗試將此函數與char類型一起使用,編譯器將拋出錯誤。

這取決於你想做什么。 如果您希望編譯器無法為函數調用找到合適的解決方案,您可以使用 Flinsch 的答案,這可能是最好的,或者您可以使用 SFINAE:

template < typename T > is_an_ok_type : boost::mpl::false_ {};
template < > is_an_ok_type<int> : boost::mpl::true_ {};
... etc...

template < typename T >
typename boost::enable_if< is_an_ok_type<T>,T >::type
get_ratio(T t1, T t2)
{
  return t1/t2;
}

如果你想要某種合理可讀的錯誤,你可以使用靜態斷言; static_assert (C++0x) 或 BOOST_STATIC_ASSERT。

由於只有longdoublefloat三種數據類型相關並且它們不需要額外的通用版本,只需拒絕template並提供longdoublefloat三個函數。

你可以這樣做:

// declaration
template <typename T> inline T getRatio(T numer, T denom);

// specialization for long    
template <>
inline long getRatio<long>(long numer, long denom) { return (numer / denom); }
// specialization for float
template <>
inline float getRatio<float>(float numer, float denom) { return (numer, denom); }
// specialization for double
template <>
inline double getRatio<double>(double numer, double denom) { return (numer / denom); }

如果使用 long、float 或 double 以外的類型調用 getRatio,這將導致鏈接器錯誤。

如果您只想將getRatio () 函數限制為int, long, double and float ,那么您也可以使用此函數。 如果您使用char類型參數調用它,它將生成“有意義的”編譯錯誤。 編譯錯誤將是: this_type_is_not_allowed_in_getRatio

//yourheader.h
template<typename T>
inline T getRatio(T numer, T denom)
{
    typedef typelist<int, typelist<long, typelist<double, float>>> allowedtypes;
    compile_time_checker<contains<allowedtypes, T>::result> this_type_is_not_allowed_in_getRatio;
    return (numer/denom);
}

它使用這個標題:

//metafunctions.h
template<typename H, typename T>
struct typelist
{
    typedef H Head;
    typedef T Tail;
};

template<typename T, typename Tail> 
struct contains
{
    static const bool result = false;
};

template<typename Head, typename Tail, typename T> 
struct contains<typelist<Head, Tail>, T>
{
    static const bool result = false || contains<Tail, T>::result;
};

template<typename T, typename Tail> 
struct contains<typelist<T, Tail>, T>
{
    static const bool result = true || contains<Tail, T>::result;
};

template<bool b> struct compile_time_checker;
template<> struct compile_time_checker<true> {};

希望,對你有幫助。 您現在可以在一個函數中編寫所有代碼!

語言中無法指定模板只能使用特定類型參數集進行實例化。 但是,對於沒有operator /定義的任何類型,這將無法編譯,這對您來說可能就足夠了。

在設計 API 時,避免讓您的用戶感到驚訝被認為是一種很好的做法,如果您告訴他們不允許計算可以被除的兩個事物的比率,大多數用戶會感到驚訝!

如果您真的不想要默認行為,Flinsch 的答案是一個很好的折衷方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM