一组类型的模板特化

时间:2010-12-03 19:11:43

标签: c++ templates

我有一个关于如何为一组数据类型专门化模板的快速问题。例如,

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

我希望这可以使用int,long,double,float,所以我想专门针对这组数据类型。因此,如果用户使用'char'类型尝试此函数,编译器将抛出错误。 如果这是一个重复让我知道。 感谢

5 个答案:

答案 0 :(得分:5)

这取决于你想做什么。如果您希望编译器无法为函数调用找到合适的分辨率,您可以使用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。

答案 1 :(得分:3)

由于只有三种数据类型longdoublefloat相关且不需要额外的通用版本,只需拒绝template并提供三种longdoublefloat的函数。

答案 2 :(得分:2)

你可以这样做:

// 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,则会导致链接器错误。

答案 3 :(得分:2)

如果您只想为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> {};

希望,它可以帮到你。 您现在可以只在一个函数中编写所有代码!

答案 4 :(得分:-1)

无法在语言中内置指定模板只能使用某组类型参数进行实例化。但是,对于没有定义operator /的任何类型,这将无法编译,这对您来说已经足够了。

在设计API时,避免让用户感到惊讶是一种很好的做法,大多数用户如果告诉他们不允许他们计算可以分割的两件事的比例就会感到惊讶!

如果你真的不想要默认行为,Flinsch的回答是一个很好的妥协。