2

これは今日仕事で出てきたので、私はそれをコミュニティに捨てようと思いました。

同僚が次のコードを書きました(多かれ少なかれ):

#include <algorithm>

double chop(double x) {
    return std::max(0, x);
}

std::maxただし、両方の引数がまったく同じ型である必要があるため、これはコンパイルすらしません。これは、参照のペアを取得して参照を返すことができるようにするためだと思います。これは、ユーザー定義型で呼び出す場合に必要になる可能性が非常に高くなります。けっこうだ。

もちろん、修正はを使用することstd::max(0.0, x)です。

私が嘘をついたので、今しばらく私と一緒に耐えてください。私の同僚が実際に書いたのはこれでした:

// Included from a very old header file written by someone long gone
template<class T1, class T2>
inline T1 myMax(T1 x, T2 y) {
    return (x < y) ? y : x;
}

double chop(double x) {
    return myMax(0, x);
}

これでコンパイルされます!しかし、たとえば0.25に等しいxに対しては、かなり驚くべき結果が得られます。彼が問題を見つけるのにどれくらいの時間がかかったかはわかりません。問題を見つけた後でも、なぜそれが機能しなかったのかを尋ねなければなりませんでした。

私の答えは、(a)0の代わりに0.0を使用する(バグを修正する)、および(b)std::maxの代わりに使用するmyMax(あなたがそれについて考えるとき、その振る舞いは非常に恐ろしい)でした。

しかし、彼はなぜそれが必要なのか疑問に思っています。0 + xつまり、彼はまたは0 * xまたはを書くことができる0 - xので、なぜmyMax(0, x)ですか?

これが彼が望むものを彼に与える最初のパスです:

// this is from the .hh file

// template meta-program to compute the "wider" of two types given as argument
template<class T1, class T2>
struct WiderType {
};

// Partial specialization for case where both types are same
template<class T>
struct WiderType<T, T> {
  typedef T type;
};

// Specialization for first type "int" and second type "double"
template<>
struct WiderType<int, double> {
  typedef double type;
};

template<class T1, class T2>
inline typename WiderType<T1,T2>::type
myMax(T1 a, T2 b) {
  return ((a < b) ? b : a);
}


// this is from the .cc file

double chop(double x) {
  return myMax(0, x);
}

// just to show this still works
int chop(int x) {
  return myMax(0, x);
}

WiderTypeこれで、整数型のすべてのペアに加えて、他の通常の算術変換を行うための特殊化を実行して追加することができました。(そして私はそれUsualConversionsか何かの名前を変更できると思います。)

しかし、もっと簡単な方法はありますか?つまり、C ++言語を使用すると、さまざまな組み込みの算術演算子と同じ変換を引数に対して実行する独自の関数を簡単に定義できますか?

4

2 に答える 2

7

チャールズベイリーの答えに加えて、これも行うことができます:

template<typename T1, typename T2>
typename std::common_type<T1, T2>::type max(T1&& a, T2&& b) {
    return a < b ? b : a;
}

common_typetypeには、両方の型を暗黙的に変換できる型であるtypedefが含まれているため、たとえば、、の場合は、を返しますが、doubleおよびの場合は、を返します。intdoubleintintint

C ++ 11をまったく使用できない場合、私が考えることができるのはこれだけです。

template<typename T1, typename T2, typename T3>
void max(const T1& a, const T2& b, T3& dst) {
    dst = a < b ? b : a;
}

のように使用します

double d;
max(0, 43.12, d);

ただし、そのように変数を宣言しなければならないのはかなり不器用です。あなたがそれがよりきれいだと思うなら、あなたはこれをすることもできます:

template<typename RetType, typename T1, typename T2>
RetType max(const T1& a, const T2& b) {
    return a < b ? b : a;
}

その後

return max<double>(0, 43.11);
于 2012-05-16T21:32:30.173 に答える
4

C ++ 11以前の良い方法はわかりませんが、今ではこのようなことができます。

template<class T, class U>
auto myMax(T&& t, U&& u) -> decltype(t + u)
{
    return t < u ? u : t;
}

decltype(t + u)共通の型が何であるかをT計算Uし、算術式に含めるだけで、それをテンプレートの戻り型として使用します。

于 2012-05-16T21:29:22.383 に答える