Поддерживают ли 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 реализуется через множественное наследование. Пример.

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