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型の前にfloat型)を作成することを考えることができます。<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 に答える