如何实现泛型最大函数

How to implement generic max function?

本文关键字:泛型 函数 实现 何实现      更新时间:2023-10-16

我知道这是因为模板函数的返回类型与第一个参数(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

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

如果可以使用 C++11,则可能需要使用尾随返回类型

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

使用

C++11 很容易,使用 std::common_type<> 特征:

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<>使用 decltype 关键字和 declval<> 特征,它们自 C++11 以来都是新的

输出正确。您从未指定过类型,因此抱怨它没有使用您希望它使用的类型是不合理的。如果需要特定类型,则必须确保两个参数都是该类型。

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

这是

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))

简单得多,不是吗?

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

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