Можно ли инициализировать несколько элементов в списке инициализаторов элементов из кортежа, полученного функцией?
Поскольку возврат нескольких значений через кортежи становится все более популярным, я надеюсь, что для этого есть решение. Я не вижу причин, кроме языковых ограничений, почему это было бы невозможно.
Это mcve для того, что у меня есть:
auto new_foo(std::size_t size) -> std::tuple<std::unique_ptr<char[]>, int*>
{
auto buffer = std::make_unique<char[]>(size * sizeof(int) + 8);
auto begin = static_cast<int*>(static_cast<void*>(buffer.get() + 4));
return std::make_tuple(std::move(buffer), begin);
}
struct X {
std::unique_ptr<char[]> buffer_{nullptr};
int* begin_{nullptr};
std::size_t size_{0};
X(std::size_t size) : size_{size}
{
std::tie(buffer_, begin_) = new_foo(size);
}
};
Можно ли это сделать ?:
X(std::size_t size)
: buffer_{ ??? },
begin_{ ??? },
size_{size}
{
}
Я просто не могу вызвать new_foo
один раз для инициализации каждого члена (поскольку он возвращает другой кортеж при каждом вызове). Так
X(std::size_t size)
: buffer_{std:get<0>(new_foo(size)},
begin_{std:get<1>(new_foo(size)},
size_{size}
{
}
это невозможно (даже если это не так, многократный вызов для получения одного и того же результата менее оптимален)
Еще одно решение, о котором я подумал, заключалось в том, чтобы хранить элементы как кортеж. Я отказался от этого, поскольку мне нужно, чтобы два члена были правильно названы внутри класса и не были доступны с помощью get<0>
и get<1>
.
Еще один обходной путь - создать простую отдельную структуру для хранения двух членов. Таким образом, они будут иметь имена, но добавить еще один уровень квалификатора, и, возможно, мне придется создать для него копию ctor (из-за unique_ptr
).
Как сообщалось, здесь C++1z
будет иметь структурированные привязки (D0144R0), что сделает это возможным:
auto {x,y,z} = f();
Поскольку я не нашел полного документа, я не могу сказать, поможет ли это в контексте списка инициализаторов членов. Я подозреваю, что нет.