Можно ли игнорировать функцию типа конечного возврата в c++11 в пользу функции вывода типа возвращаемого значения в c++14?


Когда я пропускаю возвращаемый тип выражения

Следующий код в C++11:

auto function(X x, Y y) -> decltype(x + y)
{
    return x + y;
}

Равно следующему коду в C++14:

decltype(auto) function(X x, Y y)
{
    return x + y;
}

Но дополнительно можно вывести возвращаемый тип без decltype правил в C++14:

auto function()
{
    return 0;
}

Когда я точно знаю, какой тип возврата

Следующий код в C++11:

auto function() -> int
{
    return 0;
}

Равен следующему коду в C++03:

int function()
{
    return 0;
}

Странный пример, который никогда не должен произойти

Следующий код в C++11:

auto function(X x, Y y) -> decltype(x * y)
{
    return x; // Yeah! return x with the type of x * y expression!
}

Равно следующему коду в C++14:

decltype(auto) function(X x, Y y)
{
    return static_cast<decltype(x * y)>(x);
}
Пожалуйста, поправьте меня, если приведенный выше код неверен и не работает должным образом.

Править, согласно комментарию (Yakk) : они на самом деле не равны, первый (C++11 пример) является неявным приведением, а второй (static_cast изпримера C++14 ) является явным приведением.

Заключение

Как вы можете видеть, я могу сделать все, не используя функцию альтернативного синтаксиса функций C++11. Я не ошибаюсь? Могу ли я полностью забыть об этом без каких-либо технических проблем?

В общем случае можно избежать следующего синтаксиса:

auto function() -> TYPE
{
    return 0;
}

В пользу следующего синтаксиса:

TYPE function() // TYPE can be: auto, decltype(auto), or ...
{
    return 0;
}

Не забыл ли я какое-либо использование функции трейлинг-типа возврата C++11, что невозможно с функциейвозвращаемого типа вычитания функции C++14?

1 12

1 ответ:

Есть три важных различия между функцией, использующей автоматическое вычитание типа возврата, и функцией с явным типом возврата (даже если он вычисляется):

  1. Вы не можете сделать SFINAE о вычисляемости возвращаемого типа, если вы не задаете его явно: вместо этого вы получаете жесткую ошибку. Почему? Поскольку SFINAE работает только с объявлением, а не с определением функций (SFINAE: (template-argument) substitution-failure не является ошибка).

    Автоматический-возврат-тип-вычет , без SFINAE
    SFINAE , но нет автоматического вывода типа возврата

    #include <iostream>
    int doit(int x, ...) { return x; }
    template<class X, class Y> auto doit(X x, Y y)
    #ifdef TRAILING_RETURN_TYPE
        -> decltype(doit(x) + doit(y))
    #endif
    { return doit(x) + doit(y); }
    int main() {
        std::cout << doit(1, nullptr) << std::endl;
    }
    
  2. В настоящий момент Вы не можете объявить функцию с ее фактическим типом возврата, если в определении используется автоматическое вычитание типа возврата, и она не может быть виртуальной. (Явное Правило)

    7.1.6.4 автоматический спецификатор [dcl.spec.auto]

    13 повторные объявления или специализации функции или шаблона функции с объявленный тип возврата, использующий тип заполнителя, также должен использовать этот заполнитель, а не выводимый тип.
    14 функция, объявленная с возвращаемым типом, использующим тип заполнителя, не должна быть виртуальной (10.3).

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

    auto foo() { return [] {}; }
    

Ссылка на предложение, которое было включено в проект для C++1y:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3638.html