3

このコードを検討してください:

#include <iostream>
#include <typeinfo>

using namespace std;

template<typename T1, typename T2>
auto add(T1 l, T2 r) -> decltype(l + r){
    return l + r;
}

class C {};

class B {};

class A {
public:
    C operator+(const B& b) {
        C c;
        return c;
    }
};


int main() {
    // Using add()
    A a;
    B b;
    auto c = add(a, b);

    cout << typeid(a).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;
    cout << endl;

    // Doing the same thing but not on a function
    A a2;
    B b2;
    auto c2 = a2 + b2;

    cout << typeid(a2).name() << endl;
    cout << typeid(b2).name() << endl;
    cout << typeid(c2).name() << endl;
}

非常に簡単な質問があります。なぜ、2 番目のメソッド (を使用しないメソッド) とは異なりdecltype()、後置の戻り値の型を挿入する必要があるのですか?add()add()

4

3 に答える 3

8

2 番目のメソッド (add() を使用しないメソッド) とは異なり、add() の後置戻り型に decltype() を配置する必要があるのはなぜですか?

それは C++ のルールの一部だからです。パーサーは左から右に実行されます。ほとんどの場合、識別子にまだ到達していない場合、パーサーはそのことを知りません。関数パラメーターのような識別子。

したがって、式を使用して戻り値の型を決定し、その式が何らかの方法でパラメーターを使用する場合は、関数の引数の後に戻り値の型を配置する必要があります。

しかし、私が言いたいのは、A + B が C を返すことがわかっているのに、なぜコンパイラは戻り値の型を自動的に推測できないのでしょうか?

これらは C++ の規則であるため、関数には、関数宣言で直接指定された戻り値の型が必要です。コンパイラはそれを推測できません。

まだ。

于 2012-11-28T07:45:05.277 に答える
1

add() の後置戻り型に decltype() を入れる必要があるのはなぜですか?

テンプレート関数の戻り値の型を として宣言したため、auto関数の宣言の後に何らかの方法で戻り値の型を指定する必要があります。

次のように指定することもできます。

auto add(T1 l, T2 r) -> C

ただし、たとえば整数をその関数に渡すと、うまく機能しません。

2 番目の add 関数は表示されませんが、ということoperator+であれば、その戻り値の型を指定しました。

于 2012-11-28T07:42:43.917 に答える
0

する必要はありません - 型である戻り値の型仕様に何でも入れることができます。あなたの質問が「コンパイラが正しい型を推測できないのはなぜですか?」である場合: いくつかのケースでは可能ですが、少なくとも定義を確認する必要があります。コンパイラがすでに戻り値の型を推測している場合があります: 単一の return ステートメントで構成されるラムダ

   auto l = [](int i) { return i>0; };

IIRCには、これらの戻り値の型宣言の制限を緩めるという野心があります。たとえば、あなたが提案しているように、自動戻り値の型のみを持つワンライナー関数を許可します。

于 2012-11-28T07:59:14.177 に答える