5
template <class T, class U> decltype(*(T*)(0) * *(U*)(0)) mul(T x, U y) {
   return x * y;
}

このコードは、Stroustrup のC++11 FAQから取られたものです。さまざまなタイプの 2 つのオブジェクトを乗算することを理解しています。私を困惑させているのは、テンプレート パラメーターと関数定義の間の構文です。内部で何が起こっているのdecltypeですか?0 に初期化された名前のないポインターを逆参照し、同じ方法で逆参照および初期化さTれる名前のないポインターを掛けていると思います。U私は正しいですか?

もしこれが起こっているのなら、ポインター、逆参照、および余分な括弧の使用は不必要ではないでしょうか? 目的の効果を維持しながら、このように型を初期化できませんでしたか?:

template <class T, class U> decltype(T(0) * U(0)) mul(T x, U y) {
   return x * y;
}

これは私にはずっときれいに見え最初のように2つの数値を掛けるときと同じ効果があります...

mul(4, 3); // 12

では、Stroustrup が複雑なポインター、逆参照、および初期化構文の使用に固執するのはなぜでしょうか? もちろん、これは彼が新しいauto構文を導入する前のことです。とにかく、私の質問は次のとおりです。型の初期化の上記の 2 つの形式に違いはありますか? 彼がポインターを使用して、私がしたことを単純に行うのではなく、即座にそれらを逆参照するのは、ポインターや逆参照なしで型を初期化することでしたか? 任意の応答をいただければ幸いです。

4

3 に答える 3

6

お使いのバージョンは同等ではありません。

  1. Tあなたのバージョンは、との両方Uが から構築できると想定してい0ます。行列からこれを期待するのは明らかに間違っていますが、乗算することはできます。
  2. T(0)一時的な ( にバインドされる可能性があるT&&) を生成する一方*(T*(0))で、既存のオブジェクト (つまりT&) への参照を生成するため、別の演算子が選択される可能性があります。

ただし、Stroustrup のバージョンもあなたのバージョンも実際には使用されません。同等レベルのコンパイラ実装では、次を使用します。

template <typename T, typename U>
decltype(std::declval<T>() * std::declval<U>()) mul(T x, U y);

しかし、関数の引数宣言のに戻り値の型の宣言を延期できるように構築された、遅延戻り値の型の仕様を利用できていません。引数が宣言されると、それらを使用できるようになりますauto f(int, int) -> intdecltype

template <typename T, typename U>
auto mul(T x, U y) -> decltype(x * y);

この後者の形式は、(残念ながら) 繰り返しを犠牲にして、関数本体と同じ演算子のオーバーロードを選択することが保証されています。

于 2012-11-10T14:05:00.553 に答える
5

あなたのバージョンのコードは、T と U にデフォルトのコンストラクターがあることを前提としています。Stroustrup バージョンはそうではなく、null ポインターを逆参照してダミー オブジェクトを作成します。そのコードは実行されることを意図したものではなく、結果の型を知るために解析されることのみを意図しているため、もちろん問題ではありません。

于 2012-11-10T13:26:36.603 に答える
4

decltypeコンテンツは評価されていないコンテキストです。結果が型である限り、そこに何があるかは問題ではありません。T次のように定義されることについて少し考えてみてください。

struct T
{
    int operator*(const U &) { return 2; }
};

コンストラクターを取ることも、変換可能intな型もありません。intしたがって、T(0)の未評価のコンテキストであっても、オブジェクトにはなりませんdecltype。したがって、評価されていない null 参照を使用することは、適切な型を取得する最も簡単な方法です。

T結論: コンストラクターが何を行い、何を持っているのかわからないUため、適切な型のダミー オブジェクトを参照する null 参照を使用する必要があります。

于 2012-11-10T13:27:10.323 に答える