Как я могу написать шаблон функции, который возвращает либо ссылку, либо значение? - PullRequest
0 голосов
/ 07 июня 2018

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

template<typename T>
auto&& Func()
{
  if constexpr (some_compile_time_expression)
  {
    return GetReferenceFromSomewhere();
  }
  else
  {
    return GetValueFromSomewhere();
  }
}

Это прекрасно работает для всех типов ссылок, но не работает для значений.Например, если GetValueFromSomewhere возвращает Foo, то компилятор выводит тип возврата Func как Foo&& и предупреждает, что я возвращаю временный адрес.

Есть лиспособ заставить это работать, или я вынужден как-то дразнить две ветви (через перегрузки функций или что-то подобное)?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Преторианский ответ идеален, но вы также можете узнать о std::conditional, который имеет более широкое применение.Например, рассмотрим переменную-член data_ типа int и функцию-член, которая возвращает data_ либо по ссылке, либо по значению в зависимости от некоторых условий времени компиляции:

template <bool COND>
std::conditional_t<COND, int&, int> data() { return data_; }

Это будетне может быть достигнуто с decltype(auto).Вы также можете использовать ту же технику для передачи аргументов в функции по ссылке / значению:

template <bool COND>
void f(std::conditional_t<COND, int&, int> param);

Или вы можете переключаться между конструкторами копирования / перемещения:

class X {
    X(std::conditional_t<some_cond, const X&, X&&>) = default;
    X(std::conditional_t<some_cond, X&&, const X&>) = delete;
    ...
};

И т.д. ...

0 голосов
/ 07 июня 2018

Используйте decltype(auto) для заполнителя типа возврата, он сохранит категорию точного значения функции, которую вы вызываете в операторе return

template<typename T>
decltype(auto) Func()
{
  if constexpr (some_compile_time_expression_dependent_on_T)
  {
    return GetReferenceFromSomewhere();
  }
  else
  {
    return GetValueFromSomewhere();
  }
}

Live демо

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