piecewise_construct для кортежей

Sergey K
Sergey K

У пары (std::pair) есть конструктор для поэлементного конструирования. Первым аргументом он принимает плейсхолдер std::piecewise_construct, а двумя последующими аргументами - кортежи из любого количества элементов. Каждый кортеж разбирается на элементы, которые передаются в конструктор соответствующего элемента пары как список аргументов (ожидается, что элемент пары имеет соответствующий конструктор). Кортеж является естественным обобщением пары, поэтому хотелось бы видеть такой конструктор и для кортежей.

Пример:

struct Foo {
	Foo(const Foo&) = delete;
	Foo(Foo&&) = delete;
	Foo& operator=(const Foo&) = delete;
	Foo& operator=(Foo&&) = delete;
	/* Единственный способ создания структуры -
	 * конструктор с более чем одним аргументом.
	 */
	Foo(int, float) {}
};

int main()
{
	int a = 1;
	float b = 3.14f;
	std::pair<Foo, Foo> fooPair(std::piecewise_construct, std::tie(a, b), std::tie(a, b)); // ОК
	std::tuple<Foo> fooTuple(std::piecewise_construct, std::tie(a, b)); // Ошибка - нет такого конструктора у кортежа
}

Ещё один возможный вариант использования - создание кортежа с раскрытием списка шаблонных параметров, которое делается через раскрытие sizeof и оператора "запятая":

https://stackoverflow.com/questions/22560100/how-to-initialize-all-tuple-elements-by-the-same-arguments

template <typename... TElements>
struct Container {
    // Некорректный код из ответа на SO. Нет такого конструктора.
    Container(Foo foo, Bar bar)
        : tuple(std::piecewise_construct, (sizeof(TElements), std::tie(foo, bar))...)
    {}
    std::tuple<TElements...> tuple;
};
8
рейтинг
4 комментария
Andrey Davydov
А как Вы себе представляете сигнатуру такого конструктора? Его template headers должна же будет содержать переменное число template parameter packs, как это можно выразить на C++?
Andrey Davydov
dmitriy@izvolov.ru
Andrey Davydov, на самом деле, ничего сложного: wandbox.org/permlink/7RrDix2YhNoRCpSx (пример схематичный).
dmitriy@izvolov.ru
Andrey Davydov
dmitriy@izvolov.ru, Ваша реализация делает не то же, что piecewise_construct конструктор std::pair. Вы в конструкторе ::tuple создаете элементы std::tuple и передаете их в конструктор std::tuple, т.е. это не будет работать с noncopyable & nonmovable типами.
Andrey Davydov
dmitriy@izvolov.ru
Andrey Davydov, я просто показал принцип, который заключается всего-навсего в том, чтобы в поэлементном конструкторе принимать набор кортежей. Их дальше можно проверить на совпадение с классом std::tuple через концепты или SFINAE, а дальше они разворачиваются и бросаются в конструкторы конкретных элементов.

Пример, как я и написал, схематичный. Я же не буду реализовывать полноценный кортеж ради такого простого примера.
dmitriy@izvolov.ru
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).