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

Я хочу создать гибкую шаблонную функцию, которая может принимать как 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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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

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