Допустимое использование синтаксиса в конце типа возврата на C ++ 14 - PullRequest
0 голосов
/ 01 сентября 2018

Есть ли какая-либо причина использовать следующий синтаксис:

template<typename T>
auto access(T& t, int i)
  -> decltype(t[i])
{
    return t[i];
}

Теперь, когда мы можем использовать:

template<typename T>
decltype(auto) access(T& t, int i)
{
    return t[i];
}

Синтаксис завершающего возвращаемого типа теперь кажется немного избыточным?

Ответы [ 2 ]

0 голосов
/ 01 сентября 2018

Выведенные типы возврата не относятся к SFINAE. Эта перегрузка просто выпадет из набора перегрузки, если t[i] недопустимо:

template<typename T>
auto access(T& t, int i)
  -> decltype(t[i])
{
    return t[i];
}

Принимая во внимание, что эта перегрузка не произойдет, что приведет к серьезной ошибке:

template<typename T>
decltype(auto) access(T& t, int i)
{
    return t[i];
}

Демо


Кроме того, вы можете столкнуться с проблемами с конфликтующими выведенными типами возврата. Подумай, хочу ли я вернуть std::optional<T>. Следующий код не компилируется, поскольку std::nullopt_t отличается от типа std::optional<T>:

#include <optional> // C++17 standard library feature

template <typename T>
auto foo(T const& val)
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

Завершающие типы возвращаемых значений позволяют точно указать тип возвращаемых выражений:

template <typename T>
auto foo(T const& val)
    -> decltype(val.some_function_returning_an_optional())
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

Вы можете использовать ведущий тип возвращаемого значения, но это потребует использования std::declval, что усложнит понимание:

template <typename T>
decltype(std::declval<T const&>().some_function_returning_an_optional())
foo(T const& val)
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

Демо

0 голосов
/ 01 сентября 2018

Да, как минимум три причины:

  1. Значимое объявление : Ваш первый вариант имеет объявление , которое сообщает мне, какой тип возврата; Ваш второй вариант требует, чтобы я прочитал ваше определение . Но ваше определение может быть в другом файле или не очень ясно.
  2. Ограничение типа или преобразование типа : Ваше тело может возвращать что-то отличное от выражения T[i], и, таким образом, вы получаете ограничение типа или преобразование из того, что тело возвращает в то, что вы хотите получить .
  3. Обратная совместимость : Это может показаться вам тривиальным, но попробуйте написать библиотеку и сказать своим пользователям: «О, вам нужен компилятор, совместимый с C ++ 14, из-за моего симпатичного выбора синтаксиса».

И есть еще четвертая причина в ответ Джастина .

...