1

私が観察した C++ 言語の動作を理解しようとしています (前半は理解できました)。

私のセットアップ: 2 つのテンプレート クラス:AC. Aに変換できますCが、その逆はできません。それらにはいくつかの共通の動作があるため、 と同じように動作させるためにからへCの変換のみに依存して、いくつかのロジックを実装することを探していました。例では演算子のオーバーロードを使用していますが、議論は関数またはメソッドと同じだと思います。ACAC

私が最初に試したのは、変換コンストラクターを使用することでした:

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変換可能な場合にテンプレートを推定できるのはなぜですか?CCAC


編集

私が試したコメントで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。これは、推定プロセスにパラメーターが関与していないためだと思います。

私は正しいですか?

4

1 に答える 1

4

あなたの状況は C++11、14.8.2.1/4 [temp.deduct.call] で説明されていると思います:

一般に、演繹プロセスは、演繹されたものを (上記のように型が変換された後に)A同一にするテンプレート引数値を見つけようとします。ただし、違いが認められる 3 つのケースがあります。AA

— ...

PがクラスでP、形式がsimple-template-idの場合、変換Aされた は deduced の派生クラスになることができますA。同様に、がsimple-template-idPの形式のクラスへのポインターである場合、変換された は、 deduced が指す派生クラスへのポインターになることができます。AA

[注: 14.8.1 で指定されているように、テンプレート引数推定に参加するテンプレート パラメーターがパラメーターに含まれていない場合、暗黙的な変換が関数引数に対して実行され、対応する関数パラメーターの型に変換されます。上記のリストで説明したものに加えて、このような変換も許可されます。—エンドノート]

リストされた句は、派生型は問題ないと述べており ( 14.2/1 までC<T>simple-template-idであることに注意してください)、注記では、推論プロセスの一部ではない型に対してのみ暗黙の変換が考慮されると説明されています。

于 2014-04-03T21:03:00.307 に答える