Рассматривать этот код :
#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()
)?
почему я должен поместить decltype () в возвращаемый постфиксный тип add () в отличие от второго метода (который не использует add ())?
Потому что это часть правил C ++. Парсер запускается слева направо; по большей части, если идентификатор еще не был достигнут, парсер не знает об этом. Идентификаторы как параметры функции.
Поэтому, если вы используете выражение для определения типа возвращаемого значения, и это выражение каким-то образом использует параметры, вы должны поместить возвращаемый тип после аргументов функции.
Но я хочу сказать, почему компилятор не может автоматически определить тип возвращаемого значения, когда он знает, что A + B возвращает C?
Поскольку это правила C ++: функция должна иметь тип возвращаемого значения, указанный непосредственно в объявлении функции. Компилятору не разрешено выводить это.
почему мне нужно поместить decltype () в постфиксный тип возврата add ()
Потому что вы объявили тип возврата функции шаблона как auto
, и вам нужно как-то указать тип возвращаемого значения после объявления функции.
Вы могли бы также указать это так:
auto add(T1 l, T2 r) -> C
но это не сработает, если вы передадите, например, целые числа в эту функцию.
Я не вижу 2-й функции добавления, но если вы имеете в виду operator+
, затем вы указали тип возврата для него.
Вам не нужно — вы можете поместить что-либо в спецификацию возвращаемого типа, которая является типом. Если ваш вопрос «почему компилятор не может определить правильный тип для меня?»: Я в нескольких случаях мог, но, по крайней мере, ему нужно увидеть определение. Есть случаи, когда компилятор уже делает вывести тип возврата: в лямбдах, которые состоят из одного оператора возврата
auto l = [](int i) { return i>0; };
У IIRC есть амбиции ослабить ограничения на эти декларации возвращаемого типа, например, разрешить однострочные функции только с тем типом автоматического возврата, который вы предлагаете.