Выполните инициализацию std:: tuple и std:: pair.

Агрегатная инициализация требует, помимо прочего, не предоставленных пользователем конструкторов. Но пары std::tuple и std::pair имеют большой набор перегруженных конструкторов. С точки основного языка, являются ли эти конструкторы предоставлены пользователем или даже объявлены пользователем?

С С++ 17 можно будет написать (обновить/уточнить: где nocopy - это класс, который нельзя скопировать или переместить, например std::mutex)

auto get_ensured_rvo_str(){
   return std::pair(std::string(),nocopy());
}

изменить: нет, это невозможно, как описано в ответах и ​​ответах ниже.

который требует агрегатной инициализации (для контекста: Множественные возвращаемые значения (структурированные привязки) с неизменяемыми типами и гарантированное RVO в С++ 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());

Мэтт Калабрес сделал интересный момент в списке std-предложений, который теперь мы гарантировали RVO, должно быть возможно писать компоненты, которые принимают заводы эффективно создавать своих членов на месте:

// hypothetical factory constructor
return std::pair(std::factory_construct,
    [] { return std::string{}; }, [] { return nocopy{}; });

Другим возможным направлением будет удаление конструкторов из tuple и pair (или, что более реалистично, для написания рабочих компонентов без конструкторов) и полагаться на новые расширения для агрегации инициализации, которые должны допускать агрегатную инициализацию tuple и pair, реализованную с помощью множественного наследования. Пример.