4

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

5 回答 5

10

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

如果可以使用 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

于 2012-08-28T12:13:05.383 回答
4

使用 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 以来的新特性

于 2012-08-28T12:38:35.830 回答
3

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

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

于 2012-08-28T11:49:00.617 回答
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))

简单多了,不是吗?

于 2012-08-28T12:21:30.067 回答
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;
}
于 2012-08-28T12:13:36.053 回答