Тип возвращаемого значения лямбды может быть выведен по возвращаемому значению, так почему же функция не может?

#include <iostream>

int main(){

    auto lambda = [] {
        return 7;
    };

    std::cout << lambda() << '\n';

}

Эта программа компилирует и печатает 7.
Тип возврата лямбда выводится в целочисленный тип на основе возвращаемого значения 7.


Почему это невозможно с обычными функциями?

#include <iostream>

auto function(){
    return 42;
}

int main(){

    std::cout << function() << '\n';
}

ошибка: функция 'function' использует спецификатор типа 'auto' без завершающего типа возвращаемого значения

5 ответов

Решение

C++14 имеет эту функцию. Вы можете проверить это с новыми версиями GCC или Clang, установив -std=c++1y флаг.

Живой пример

В дополнение к этому, в C++14 вы также можете использовать decltype(auto) (который отражает decltype(auto) как переменные) для вашей функции, чтобы вывести свое возвращаемое значение, используя decltype семантика.

Примером может служить функция переадресации, для которой decltype(auto) особенно полезно:

template<typename function_type, typename... arg_types>
decltype(auto) do_nothing_but_forward(function_type func, arg_types&&... args) {
    return func(std::forward<arg_types>(args)...);
}

С использованием decltype(auto)Вы имитируете фактический тип возврата func при вызове с указанными аргументами. Больше нет дублирования кода в конце типа возврата, что очень печально и подвержено ошибкам в C++11.

Это всего лишь ограничение того, как язык создавался и развивался. В следующем стандарте C++14 возвращаемый тип функции может быть выведен в некоторых контекстах, но не во всех. Существуют сложности, когда есть несколько операторов возврата.

Кроме того, у выведенных типов возврата есть и другие проблемы, например, тип возврата функции шаблона нельзя использовать в контексте SFINAE, так как для возможности определения типа компилятор должен создать экземпляр шаблона функции, что происходит после подстановки. Конечным результатом является то, что, хотя эта функция появится в ближайшем будущем, я бы ее избегал, если бы вы могли предоставить тип самостоятельно.

Это происходит в C++14. Смотрите следующее предложение.

Его еще нет... он будет в C++1y/C++14.. проверьте эту ссылку функции

Я предполагаю, что это, вероятно, потому что выведенные по типу лямбды не могут быть рекурсивными.

Почему это важно? Потому что если лямбда с выводом типа может быть рекурсивной (под "выводом типа" я подразумеваю, где имя переменной имеет тип auto), тогда его возвращаемый тип потенциально может зависеть от самого себя - и хотя иногда это можно решить, его гораздо сложнее реализовать, чем "простой" вывод типа. Я даже не уверен, что это всегда разрешимо (это разрешимо в общем случае?). Если бы функции поддерживали вывод типов, тем не менее, об этой проблеме нужно было бы позаботиться, поэтому, вероятно, они просто исключили их по этой причине.

Другие вопросы по тегам