Включение NRVO при пересылке результата функции через функцию шаблона

При пересылке результата функции через функцию шаблона я столкнулся с различным поведением в отношении использования «оптимизации именованного возвращаемого значения (NRVO)» для clang и gcc. Вот фрагмент кода:

Foo provideFooAsTemporary() 
{
    return Foo{};
}

template <typename TFn>
auto forwardA(TFn &&fn) 
{
    auto result = fn();
    return result;
}

template <typename TFn>
auto forwardB(TFn &&fn) -> decltype(fn()) 
{
    auto result = fn();
    return result;
}

Foo fooA = forwardA(provideFooAsTemporary);  
Foo fooB = forwardB(provideFooAsTemporary);

Вот мои наблюдения (также см. пример с болтом):

  • gcc 14.1: Избегает любых операций перемещения как для forwardA, так и для forwardB.

  • clang 18.0.1: Избегает перемещения только для forwardB, но операция перемещения выполняется для forwardA.

Я ожидал, что forwardA запускает NRVO также и для лязга.

Вот мои вопросы:

  1. В чем именно разница между forwardA и forwardB? Почему указанный конечный тип возвращаемого значения имеет значение?

  2. Есть ли более простой способ включить NRVO для clang, чем тот, который показан на forwardB?

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Удивительно, но это известная проблема в текущей реализации NRVO в Clang:

Если шаблон функции использует выведенный тип возвращаемого значения (т. е. auto или decltype(auto)), то NRVO не применяется ни для какой реализации этого шаблона функции.

См., например. отчеты об ошибках

и, возможно, еще больше других.

Насколько я понимаю, на самом деле нет никакой причины, по которой применение NRVO должно зависеть от того, указан ли явно тип возвращаемого значения. Кажется, это ограничение текущего подхода к реализации.

Однако с точки зрения соответствия NRVO никогда не гарантируется, и компилятор всегда волен не применять его. Его невозможно заставить это сделать.

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