В чем смысл std::make_optional
Все std::make_
делаются избыточными в C++17 с введением вывода аргументов шаблона класса (кромеmake_unique
а также make_shared
).
Так в чем смысл std::make_optional
? Насколько я могу судить, он делает то же самое, что и руководство по дедукции дляstd::optional
.
Есть ли сценарий, когда std::make_optional
предпочтительнее руководств по дедукции?
2 ответа
Один из примеров различий - когда вы хотите (по какой-либо причине) сделать необязательный параметр, содержащий необязательный:
#include <optional>
#include <type_traits>
int main()
{
auto inner=std::make_optional(325);
auto opt2=std::make_optional(inner); // makes std::optional<std::optional<int>>
auto opt3=std::optional(inner); // just a copy of inner
static_assert(std::is_same_v<decltype(opt2), std::optional<std::optional<int>>>);
static_assert(std::is_same_v<decltype(opt3), std::optional<int>>);
}
Другим примером использования for может быть создание объекта, хранящегося в a, без создания для него временного объекта, когда его конструктор принимает несколько аргументов.
Например, рассмотрим следующий класс, конструктор которого имеет несколько аргументов:
struct Point3D {
Point3D(int xx, int yy, int zz): x(xx), y(yy), z(zz) {}
int x, y, z;
};
Представьте, что вы хотите инициализировать объект, хранящийся в
Point3D(1, 2, 3)
X , тогда вы можете действовать следующим образом:
std::optional oPoint = Point3D(1, 2, 3);
Однако это создаст временный объект, который затем будет перемещен в папку . Вместо этого, используя шаблон функции удобства, вы можете избежать создания этого временного объекта:
auto oPoint = std::make_optional<Point3D>(1, 2, 3);
Поскольку мы говорим здесь о C++17 (т.е.
std::optional
был введен в C++17), здесь применяется гарантированное удаление копии , и поэтому временный объект не создается.
Обратите внимание, что вы все еще можете избежать создания временного объекта без использования, передав
std::in_place
к конструктору
std::optional<Point3D>
объект:
std::optional<Point3D> oPoint{std::in_place, 1, 2, 3};
Это создаст сохраненный
Point3D
объект на месте , что позволяет избежать создания временного. Тем не менее, вы можете найти это более подробным, чем подход с
std::make_optional()
.
Икс
std::optional<Point3D> oPoint(1, 2, 3);
не компилируется.