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;
}

我只是有一个非常简单的问题:为什么我需要在第二种方法(不使用的方法)中放入不同decltype()的后缀返回类型?add()add()

4

3 回答 3

8

为什么我需要将 decltype() 放在 add() 的后缀返回类型中,这与第二种方法(不使用 add() 的方法)不同?

因为这是 C++ 规则的一部分。解析器从左到右运行;在大多数情况下,如果尚未达到标识符,则解析器不知道它。标识符如函数参数。

因此,如果您使用表达式来确定返回值的类型,并且该表达式以某种方式使用参数,则必须将返回类型放在函数参数之后。

但是我的观点是,为什么编译器知道A + B返回C时不能自动推断返回类型?

因为这些是 C++ 的规则:函数必须具有直接在函数声明中指定的返回类型。不允许编译器推断它。

然而。

于 2012-11-28T07:45:05.277 回答
1

为什么我需要将 decltype() 放在 add() 的后缀返回类型中

因为您将模板函数的返回类型声明为auto,并且您需要在函数声明之后以某种方式指定返回类型。

您也可以像这样指定它:

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

但是,如果您将例如整数传递给该函数,那将不会很好地工作。

我没有看到第二个 add 函数,但如果你的意思是operator+,那么你指定了它的返回类型。

于 2012-11-28T07:42:43.917 回答
0

您不必这样做 - 您可以在返回类型规范中放入任何类型的内容。如果您的问题是“为什么编译器不能为我推断出正确的类型?”:在少数情况下,它可以,但至少它需要查看定义。在某些情况下,编译器已经推断出返回类型:在由单个 return 语句组成的 lambdas 中

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

IIRC 雄心勃勃地放宽对这些返回类型声明的限制,例如,允许像您建议的那样仅使用自动返回类型的单行函数。

于 2012-11-28T07:59:14.177 回答