Можно ли явно привести prvalue к константной ссылке, чтобы избежать дополнительного копирования в тернарном операторе? ⇐ C++
Можно ли явно привести prvalue к константной ссылке, чтобы избежать дополнительного копирования в тернарном операторе?
Предположим, у нас есть некоторый некопируемый и неперемещаемый тип Foo и функция
int f(const Foo& foo) { ... // каким-то образом вычисляем результат в зависимости от значения foo. } Теперь предположим, что мы хотим вызвать эту функцию следующим образом:
const Foo foo1{ 42 }; логическое условие = getCondition(); int result = f (условие? foo: Foo {150}); Это не скомпилируется, поскольку foo и Foo{ 150 относятся к разным категориям значений, поэтому по определению тернарный оператор вернет prvalue типа < code>Foo — это означает, что foo1 необходимо будет скопировать, если condition == true, поэтому это вызывает ошибку компиляции.
Однако C++ гарантирует, что временные объекты остаются действительными до конца выражения, поэтому вместо этого мы можем написать следующее:
const Foo foo1{ 42 }; логическое условие = getCondition(); int result = f (условие? foo: static_cast(Foo{ 150 }); Теперь тернарный оператор возвращает const Foo&, и даже если эта ссылка ссылается на Foo{ 150 , этот временный объект останется действительным до конца выражения. Никакого копирования/перемещения не происходит, поэтому это компилируется.
Очевидно, безопаснее было бы просто написать:
int result = условие? е(фу): е(фу{150}); Однако это может привести к появлению большого количества шаблонов, если есть дополнительные параметры, и экспоненциально растет для нескольких «условных» параметров:
int result =condition1 ? (условие2 ? f(foo1, foo2) : f(foo1, Foo{ 222 })) : (условие2 ? f(Foo{ 111 }, foo2): f(Foo{ 111 }, Foo{ 222 })); Приведенный выше хак позволяет использовать более короткую форму:
int result = f(condition1? foo1: static_cast(Foo{ 111 }), условие2 ? foo2 : static_cast(Foo{ 222 }) ); Я понимаю, что это сопряжено с некоторым риском, но правильно ли я считаю, что приведенный выше код действителен?
П.С. Мне также интересно, генерирует ли компилятор инструкции O(N) или O(2^N) при наличии N таких «условных» параметров.
Тернарный оператор и продление времени жизни временного объекта с помощью ссылки на константу рассматривают аналогичный сценарий, но вопрос в том, продлевает ли сам тернарный оператор время жизни временного объекта - это не так.
Предположим, у нас есть некоторый некопируемый и неперемещаемый тип Foo и функция
int f(const Foo& foo) { ... // каким-то образом вычисляем результат в зависимости от значения foo. } Теперь предположим, что мы хотим вызвать эту функцию следующим образом:
const Foo foo1{ 42 }; логическое условие = getCondition(); int result = f (условие? foo: Foo {150}); Это не скомпилируется, поскольку foo и Foo{ 150 относятся к разным категориям значений, поэтому по определению тернарный оператор вернет prvalue типа < code>Foo — это означает, что foo1 необходимо будет скопировать, если condition == true, поэтому это вызывает ошибку компиляции.
Однако C++ гарантирует, что временные объекты остаются действительными до конца выражения, поэтому вместо этого мы можем написать следующее:
const Foo foo1{ 42 }; логическое условие = getCondition(); int result = f (условие? foo: static_cast(Foo{ 150 }); Теперь тернарный оператор возвращает const Foo&, и даже если эта ссылка ссылается на Foo{ 150 , этот временный объект останется действительным до конца выражения. Никакого копирования/перемещения не происходит, поэтому это компилируется.
Очевидно, безопаснее было бы просто написать:
int result = условие? е(фу): е(фу{150}); Однако это может привести к появлению большого количества шаблонов, если есть дополнительные параметры, и экспоненциально растет для нескольких «условных» параметров:
int result =condition1 ? (условие2 ? f(foo1, foo2) : f(foo1, Foo{ 222 })) : (условие2 ? f(Foo{ 111 }, foo2): f(Foo{ 111 }, Foo{ 222 })); Приведенный выше хак позволяет использовать более короткую форму:
int result = f(condition1? foo1: static_cast(Foo{ 111 }), условие2 ? foo2 : static_cast(Foo{ 222 }) ); Я понимаю, что это сопряжено с некоторым риском, но правильно ли я считаю, что приведенный выше код действителен?
П.С. Мне также интересно, генерирует ли компилятор инструкции O(N) или O(2^N) при наличии N таких «условных» параметров.
Тернарный оператор и продление времени жизни временного объекта с помощью ссылки на константу рассматривают аналогичный сценарий, но вопрос в том, продлевает ли сам тернарный оператор время жизни временного объекта - это не так.
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Должен ли std::span передаваться по значению или по константной ссылке? [дубликат]
Anonymous » » в форуме C++ - 0 Ответы
- 25 Просмотры
-
Последнее сообщение Anonymous
-