如何实现泛型最大函数?

时间:2012-08-28 11:44:47

标签: c++ templates

我知道这是因为模板函数的返回类型与第一个参数(T)的返回类型相同 如何修改此模板,使其在所有情况下都能正常运行?

#include <iostream>
using namespace std;
template <typename T, typename U>
T max(T x, U y)
{
    return x>y ? x : y;
}

int main()
{
    cout<<max(17.9,17)<<"\n";
    cout<<max(17,17.9)<<"\n";
}

输出

17.9  
17

5 个答案:

答案 0 :(得分:10)

实现的行为是正确的,但您可能不需要该输出。代码中返回类型的问题。

如果可以使用C ++ 11,则可能需要使用trailing-return type

template <typename T, typename U>
auto max(T x, U y) -> decltype(x>y ? x : y)    //C++11 only
{
    return x>y ? x : y;
}

将提供此输出:

17.9
17.9

我希望这是理想的输出。

在线演示:http://ideone.com/2Sh5Y

答案 1 :(得分:4)

使用c ++ 11很简单,使用std :: common_type&lt;&gt;性状:

template <typename T, typename U>
typename std::common_type<T,U>::type max(T x, U y) /// why not const& T and const& U ?
{
    return x>y ? x : y;
}

common_type&LT;&GT;使用decltype关键字和declval&lt;&gt;自c ++ 11以来都是新的特质

答案 2 :(得分:3)

输出正确。你从来没有指定过类型,所以抱怨它没有使用你想要它使用的类型是不合理的。如果您想要特定类型,则必须确保 这两个参数类型。

您可以将第一个参数转换为double。或者你可以专门调用
max<double, double>。如果你真的想要,你也可以专注max<int, double>和类似的组合。

答案 3 :(得分:2)

这是C ++ 03的答案。对于C ++ 11 - 使用auto / decltype(参见其他答案)。

您必须创建另一个模板:template CommonNumericType<T1,T2>

template <typename L, typename R>
typename CommonNumericType<T1,T2>::Type max(L x, R y)
{
    return x>y ? x : y;
}

为每一对可能的数字类型专门化这个CommonNumericType:

template <typename L, typename R>
struct CommonNumericType;
template <typename T>
struct CommonNumericType<T,T> {
   typedef T Type;
};
template <typename L>
struct CommonNumericType<L,long double> {
   typedef long double Type;
};
template <typename R>
struct CommonNumericType<long double,R> {
   typedef long double Type;
};
// ...
template <>
struct CommonNumericType<int,short> {
   typedef int Type;
};
// and many others stuff

我可以考虑制作一些数字类型层次结构 - 在int类型之前浮点类型 - 依此类推。因为<number of numeric types>^2是一个非常大的数字:

template <typename T>
struct NumericTypeOrder;
template <>
struct NumericTypeOrder<long double> { enum { VALUE = 1 }; };
template <>
struct NumericTypeOrder<double> { enum { VALUE = 2 }; };
template <>
struct NumericTypeOrder<float> { enum { VALUE = 3 }; };
template <>
struct NumericTypeOrder<unsigned long long> { enum { VALUE = 4 }; };
// etc for all numeric types - where signed char is last one...

template <typename L, typename R, bool L_bigger_than_R>
struct CommonNumericTypeImpl;
template <typename L, typename R>
struct CommonNumericTypeImpl<L,R,true> {
  typedef L type;
};
template <typename L, typename R>
struct CommonNumericTypeImpl<L,R,false> {
  typedef R type;
};
template <typename L, typename R>
struct CommonNumericType 
: CommonNumericTypeImpl<L,R,NumericTypeOrder<L>::value >= NumericTypeOrder<R>::value > {
};

或者只使用宏:

#define max(l,r) ((l) >= (r) ? (l) : (r))

更简单,不是吗?

答案 4 :(得分:1)

在C ++ 11中,您可以使用类型推断(使用auto,延迟返回类型和decltype):

template <typename T, typename U>
auto max(T x, U y) -> decltype(x>y ? x : y)
{
  return x>y ? x : y;
}