Поддерживают ли std::tuple и std::pair агрегатную инициализацию?
Агрегированная инициализация не требует, среди прочего, никаких пользовательских конструкторов. Но std::tuple
а также std::pair
В паре есть большой набор перегруженных конструкторов. С точки зрения основного языка, эти конструкторы предоставлены пользователем или даже объявлены пользователем?
С C++17 можно будет писать (обновление / уточнение: где nocopy - это класс, который нельзя скопировать или переместить, например, std::mutex
)
auto get_ensured_rvo_str(){
return std::pair(std::string(),nocopy());
}
изменить: нет, это невозможно, как объяснено в связи с ответами и ответом ниже.
которая требует агрегатной инициализации (для контекста: множественные возвращаемые значения (структурированные привязки) с неподвижными типами и гарантированным RVO в C++17).
Являются tuple
а также pair
поддерживается специальным стандартным языком, чтобы разрешить это (при наличии конструкторов)?:
20.5.2.1 Строительство
... EXPLICIT constexpr tuple (const Types &...);
6 Эффекты: конструктор инициализирует каждый элемент значением соответствующего параметра.
или мы можем в принципе написать свой tuple
или же pair
?
1 ответ
Нет, поддержки нет tuple
или же pair
для передачи типов без перемещения их конструкторам, и, как вы заметили, их не может быть, поскольку аргумент конструктора и член кортежа (или пары) могут быть разными объектами:
// exposition only
template<class... Us>
tuple(Us&&... us) : values{std::forward<Us>(us)...} {}
^^ these
^^^^^^ are different objects to these
Вы должны использовать кусочную конструкцию:
return std::pair<std::string, nocopy>(std::piecewise_construct,
std::forward_as_tuple(), std::forward_as_tuple());
Мэтт Калабрезе (Matt Calabrese) отметил интересный момент в списке стандартных предложений: теперь, когда мы гарантируем RVO, должна быть возможность писать компоненты, которые принимают фабрики для эффективного создания своих членов:
// hypothetical factory constructor
return std::pair(std::factory_construct,
[] { return std::string{}; }, [] { return nocopy{}; });
Другим возможным направлением будет удаление конструкторов из tuple
а также pair
(или, что более реалистично, для написания рабочих компонентов без конструкторов) и полагаться на новые расширения для агрегированной инициализации, которая должна позволять агрегированную инициализацию tuple
а также pair
реализуется через множественное наследование. Пример.