Конечный тип возврата, выведенный из входных аргументов конкретного варианта использования - PullRequest
2 голосов
/ 18 октября 2019

Я видел, что одна из всегда приводимых причин использования конечных возвращаемых типов - это когда мы хотим вывести возвращаемый тип из входных аргументов. Я знаю, что есть и другие причины, но я фокусируюсь именно на этом конкретном вопросе.

Один из приведенных примеров:

template <typename T>
auto func(const T & t) -> decltype(std::cout << t)
{
    return std::cout << t;
}

Но я не смогвыяснить любой конкретный вариант использования этого.

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

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

Приведенный выше пример можно переписать так:

template <typename T>
std::ostream& func(const T & t)
{
    return std::cout << t;
}

На мой взгляд, это менее многословно и более читабельно, чем конечная версия возвращаемого типа.

Чего мне не хватает?

Ответы [ 2 ]

7 голосов
/ 18 октября 2019

Я имею в виду, мы всегда знаем тип возвращаемого значения функции, когда пишем ее

А мы? Итак, если вы напишите этот шаблон функции:

template<typename A, typename B>
/* ret */ foo(A a, B b) {
  return a + b;
}

Вы можете точно сказать, что такое ret? Если задано два целых числа, то это, конечно, целое число. Но если указано целое и длинное, оно должно быть длинным из-за рекламных акций. И если один аргумент является двойным, то результатом должно быть двойное два.

А что, если это два объекта некоторых типов классов? Теперь мы вызываем перегруженный operator+, и совершенно неясно, что он может вернуть.

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

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

1 голос
/ 18 октября 2019

Приведенный выше пример можно переписать так:

Нет, это невозможно. Ваш вывод основан на предположении, что есть:

std::ostream& operator<<(std::ostream&,const T&);

Но это не обязательно так. Это может быть

any_other_type operator<<(std::ostream&,const T&);

Тогда ваша версия метода не сможет скомпилироваться, в то время как версия с выведенным типом возврата будет в порядке.

Для конкретного случая использования рассмотрим некоторую манипуляцию с io, которая позволяет вам писать код, такой как

std::cout << all_caps_modifier << "some text" << back_to_normal_modifier << " more text";

, который будет печатать:

SOME TEXT more text

Я допускаюэто довольно надуманный пример, но использование прокси-сервера, который инкапсулирует std::cout и делает печать строки заглавными буквами, является возможным способом ее реализации (std::cout << all_caps_modifier вернет тип, отличный от std::ostream&).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...