Моя функция шаблона с универсальной ссылкой не работает

Я хочу создать гибкую шаблонную функцию, которая может принимать как rvalue, так и lvalue. Вот как я это написал:

template<typename T>
decltype(auto) normalize_pose(T&& pose)
{
    if (pose > 2 * M_PI) return std::forward<T>(pose - 2* M_PI);
} 

Поэтому я дважды проверил функцию, и она кажется мне правильной. Тогда я решил проверить это и написал:

int a = 2;
auto test = factorgraph::normalize_pose(a);

Я получаю эту ошибку:

 error: use of ‘decltype(auto) factorgraph::normalize_pose(T&&) [with T = int&]’ before deduction of ‘auto’

Если я пытаюсь добавить <int>, я получаю сообщение об ошибке, что такой функции не существует.

А как насчет ветки else? Что бы функция вернула if(not)?

User Using 22.05.2019 16:32

Кстати, ваш пример странный, так как переадресация не нужна, здесь работает const ref.

Jarod42 22.05.2019 16:32

@ Jarod42 Вы имеете в виду из-за правила вывода типа шаблона?

aikhs 22.05.2019 16:33

Вы не говорите, какую версию С++ вы компилируете. Использование умных выведенных типов возврата должно быть лучше, чем C++11

Gem Taylor 22.05.2019 16:34

@UsingCpp Это ответ!!!! Он не смог вывести тип на моем примере, о боже, какой же я тупой...

aikhs 22.05.2019 16:35

@GemTaylor Да, тег добавлен

aikhs 22.05.2019 16:35

Я не могу воспроизвести это сообщение об ошибке.

Brian Bi 22.05.2019 16:37

@Brian Попробуйте с int a = 2, код будет вне оператора if, и auto не сможет определить тип, я должен был добавить, какой int я использовал

aikhs 22.05.2019 16:38

Все равно не могу воспроизвести. Аргументы, передаваемые во время выполнения, не должны вызывать ошибки времени компиляции. См. coliru.stacked-crooked.com/a/b09f50dbccdb549f

Brian Bi 22.05.2019 16:42
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
2
9
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Так должно быть

if (pose > 2 * M_PI) return std::forward<T>(pose) - 2* M_PI;

Применить std::forward только к переменной.

И вам также нужно вернуть значение для ветки else (того же типа, чтобы удовлетворить decltype(auto)).

Но в вашем случае просто:

template<typename T>
auto normalize_pose(const T& pose)
{
    return (pose > 2 * M_PI) ? pose - 2 * M_PI : pose;
}

справляется со всеми делами.

Да правильно, но я все еще получаю эту ошибку: error: use of ‘decltype(auto) factorgraph::normalize_pose(T&&) [with T = int&]’ before deduction of ‘auto’ auto test = factorgraph::normalize_pose(a);

aikhs 22.05.2019 16:32

Почти уверен, что decltype(auto) также не нужен, поскольку std::forward<T>(pose) - 2* M_PI, скорее всего, является выражением prvalue, а ветвь else - нет.

NathanOliver 22.05.2019 16:39

@NathanOliver Не знаю, ребята, я здесь, чтобы учиться, если это необходимо. Я просто следовал примеру из книги "Effective Modern C++"

aikhs 22.05.2019 16:41

Несвязанный: decltype(auto) просто может быть T. Я не знаю, почему ОП хочет этого!

User Using 22.05.2019 16:45

Обновленный код завершается ошибкой, если передается целое число: coliru.stacked-crooked.com/a/13731e038276b632

NathanOliver 22.05.2019 16:45

Хотя это может быть спорным, поскольку нормализация int не имеет большого смысла.

NathanOliver 22.05.2019 16:46

@UsingCpp Согласно книге, о которой я упоминал, это должен быть decltype, потому что автоматически отсекается часть & из-за правила вывода типа шаблона.

aikhs 22.05.2019 16:46

@NathanOliver, потому что это не всегда целое число, что, если я указал число с плавающей запятой?

aikhs 22.05.2019 16:47

Это все еще не работает из-за decltype(auto). Вы действительно хотите вернуть ссылку?

NathanOliver 22.05.2019 16:48

@NathanOliver Нет, но в некоторых случаях возврат ссылки будет важен.

aikhs 22.05.2019 16:49

@NathanOliver Думаю, на этом мои знания заканчиваются. Можете ли вы объяснить, что именно может пойти не так с этим кодом?

aikhs 22.05.2019 16:52

@НатанОливер: исправлено. Не хотел так сильно менять код OP. (вероятно, мы тоже можем избавиться от шаблона и просто использовать double).

Jarod42 22.05.2019 16:52

@Jarod42 Jarod42 Но что произойдет, если я укажу &int? Я предполагаю, что возвращаемое значение T будет int?

aikhs 22.05.2019 16:53

@Edmund Код в том виде, в каком он есть сейчас, действительно то, что вам нужно. Использование decltyp(auto) для получения возвращаемой ссылки не может работать, потому что pose - 2 * M_PI не будет иметь тот же тип, что и pose. Чтобы decltype(auto) работал, все пути управления должны возвращать один и тот же тип, и вы просто не можете этого сделать в этой ситуации.

NathanOliver 22.05.2019 16:54

@NathanOliver Вы имеете в виду, что если pose имеет значение int, тип возвращаемого значения будет двойным / плавающим?

aikhs 22.05.2019 16:55

@ Эдмунд Нет. Допустим, T - это двойник. тогда pose - 2 * M_PI будет типа double. pose, с другой стороны, будет иметь тип double const &, поскольку это тип pose. double и double const & не одного типа, поэтому decltype(auto) не работает. Вы можете использовать решение Джарода, а затем, если вам нужно нормализованное значение, а также установить переменную на это нормализованное значение, вы можете использовать что-то вроде auto foo = (bar = normalize(bar)) * more_stuff;

NathanOliver 22.05.2019 16:59

@NathanOliver Просто быстрый вопрос, так почему же автор Effective Modern C++ пишет это как хороший пример? template<typename Container, typename Index> decltype(auto) authAndAccess(Container&& c, Index i) { authenticateUser(); return std::forward<Container>(c)[i]; }

aikhs 22.05.2019 17:03

@Edmund Потому что эта функция может возвращать только один тип. Это означает, что они могут возвращать точный ссылочный тип. Если бы функция была template<typename Container, typename Index> decltype(auto) authAndAccess(Container&& c, Index i) { if (authenticateUser()) return std::forward<Container>(c)[i]; else return foo; }, то вы возвращаете 2 разных типа, и она не может работать.

NathanOliver 22.05.2019 17:05

@NathanOliver Хорошо, но если возвращаемый тип else был двойным (например, умноженным на M_PI), то мой пример кода будет действительным?

aikhs 22.05.2019 17:07

Давайте продолжить обсуждение в чате.

NathanOliver 22.05.2019 17:08

Другие вопросы по теме