私が観察した C++ 言語の動作を理解しようとしています (前半は理解できました)。
私のセットアップ: 2 つのテンプレート クラス:A
とC
. A
に変換できますC
が、その逆はできません。それらにはいくつかの共通の動作があるため、 と同じように動作させるためにからへC
の変換のみに依存して、いくつかのロジックを実装することを探していました。例では演算子のオーバーロードを使用していますが、議論は関数またはメソッドと同じだと思います。A
C
A
C
私が最初に試したのは、変換コンストラクターを使用することでした:
template <class T>
class A {
};
template <class T>
class C {
public:
C() = default;
C(const A<T>&) {};
};
template <class T>
bool operator<(const C<T> &, const C<T> &) {return true;}
int main() {
A<int> a1, a2;
C<int> c1, c2;
c1 = a1; // OK, no-brainer
c1 < c2; // OK, no-brainer
c1 < a1; // template deduction failure
a1 < c1; // template deduction failure
a1 < a2; // template deduction failure
}
これは実際にSOとネットを検索して理解したと思う前半です。私が収集したものから、変換を試行する前にテンプレート引数を正確に一致させる必要があります。この場合、可能な変換を考慮せずに推定することはできないため、推定は不可能です。これは、オペレータが非テンプレート フレンドになると回避できますC
(しかし、私はそれが好きではありません)。
次に試したのは、継承を使用することでした。
template <class T>
class C {
};
template <class T>
class A : public C<T> {
};
template <class T>
bool operator<(const C<T> &, const C<T> &) {return true;}
int main() {
A<int> a1, a2;
C<int> c1, c2;
c1 = a1; // Ok, slicing
c1 < c2; // Ok, no-brainer
c1 < a1; // Ok, but why?
a1 < c1; // Ok, but why?
a1 < a2; // Ok, but why?
}
これについては、ネット上で説明が見つかりませんでした(検索方法がわからなかったのかもしれません)。
私の質問は、(2 番目のケース)の基本クラスであるが、 (1 番目のケース)に変換可能な場合は推定できないため、A
変換可能な場合にテンプレートを推定できるのはなぜですか?C
C
A
C
編集
私が試したコメントでKerrekSBが示唆したように:
template <class T>
bool operator<(const C<T> &, const typename std::common_type<C<T>>::type &) {return true;}
私の最初のケース(継承ではなく変換)
この場合:
c1 < c2; // OK
c1 < a1; // OK, a1 is converted
a1 < c1; // template deduction failure
a1 < a2; // template deduction failure
c1 < a1
彼の答えを使用すると、2 番目の引数は推論プロセスの一部ではないため、2 番目の引数では暗黙の変換が考慮されるため、うまくいくと思います。
私も試しました:
template <class T>
bool operator<(const typename std::common_type<C<T>>::type &, const typename std::common_type<C<T>>::type &) {return true;}
これでも動作しませんc1 < c2
。これは、推定プロセスにパラメーターが関与していないためだと思います。
私は正しいですか?