Возвращаемый шаблонной функцией тип

230
27 февраля 2018, 05:53

В книге Стенли Липпмана(Базовый курс по с++) написано, что если тип возвращаемый шаблонной функцией отличается от типа параметра шаблона, то можно использовать замыкание:

template<typename Iterator>
auto process(const Iterator& beg, const Iterator& end)->decltype(*beg) {
    /*SOMECODE*/
    return *end;
}

Вопрос 1:

Если возвращаемый тип будет результатом сложных вычислений, мне дублировать их в decltype(/вычисления/)?

Вопрос 2:

Какие преимущества использование замыкания по сравнению с использованием спецификатора auto для выведения возвращаемого типа (код далее)

template<typename Iterator>
auto process(const Iterator& beg, const Iterator& end) {
    /*SOMECODE*/
    return *end;
}
Answer 1

Не совсем понимаю, что и почему вы называете "замыканием".

Если возвращаемый тип будет результатом сложных вычислений, мне дублировать их в decltype(/вычисления/)?

Да, если вы хотите воспользоваться именно C++11 синтаксисом с -> decltype(что-то).

Однако начиная с C++14 у вас есть возможность использовать auto (или decltype(auto)) в качестве типа возвращаемого значения и не указывать этот хвост с -> decltype(что-то) вообще. В такой ситуации тип возвращаемого значения будет выведен автоматически из типа аргумента return.

Вопрос 2: Какие приемущества использование замыкания по сравнению с использованием спецификатора auto для выведения возвращаемого типа

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

В выводимом варианте такой возможности нет. Если разные return будут возвращать значения разных типов, тот дедукция будет неоднозначной и код просто не будет компилироваться.

То есть это совершенно разные модели поведения и дело тот не в преимуществах, а в том, какая именно модель вам нужна: 1) жестко заданный тип с приведением, или 2) выводимый тип с требованием единообразия.

Answer 2

Тут стоило бы начать с того, что правила вывода типа для auto и decltype различны. Например, если в качестве Iterator используется std::vector<std::string>::iterator, то возвращаемые типы будут различны:

  1. экземпляр std::string (иницилизированный вызовом конструктора копирования).
template<typename Iterator>
auto process(const Iterator& beg, const Iterator& end)
template<typename Iterator>
auto process(const Iterator& beg, const Iterator& end) -> std::remove_reference_t<decltype(*beg)>
  1. ссылка std::string &
template<typename Iterator>
decltype(auto) process(const Iterator& beg, const Iterator& end)
template<typename Iterator>
auto process(const Iterator& beg, const Iterator& end) -> decltype(*beg)

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

READ ALSO
LLVM &amp; Clang++ AST

LLVM & Clang++ AST

Установил Clang по гайду и обнаружил, что LLVM\include нет папок clang и llvm (есть clang-с и llvm-с)

204
В массиве выводится мусор (Задача на нахождение одинаковых элементов в динамических массивах)

В массиве выводится мусор (Задача на нахождение одинаковых элементов в динамических массивах)

Дано два динамических массива одинаковой размерностиНужно вывести массив с одинаковыми элементами этих массивов

205
Неправильно работающая программа. Win32, Direct2D

Неправильно работающая программа. Win32, Direct2D

Картинка почему то постоянно обновляется, и происходит постоянное выделение памяти без освобождения

183
Как ArrayList &lt;Integer&gt; заполнить с клавиатуры?

Как ArrayList <Integer> заполнить с клавиатуры?

Как ArrayList <Integer> заполнить с клавиатуры?

193