2016-07-26 4 views
2

Я хотел бы иметь кортеж, который имеет элемент массива в качестве члена. В частности, я бы хотел, чтобы этот элемент массива был 2D, поэтому любой ответ должен работать более чем на 1D. Мне бы хотелось, чтобы я мог инициализировать списки инициализаторов, например. std::tuple<ARRAY_TYPE, ...>({{0, 1}, {2, 3}}, ...).Что такое однострочное выражение для построения кортежа C++ с элементом массива (C или std :: array)?

Похоже, что такой кортеж очень сложно построить, требуя ручной инициализации (то есть для петель и т. П.). Вот что я пробовал:

std::tuple<int[M][N], ...> - это не работает из-за ограничений массивов в стиле C. Сам кортеж является допустимым типом, но инициализация должна выполняться вручную (не при построении).

std::tuple<std::array<std::array<int, M>, N>, ...> - Я думал, что это сработает, но по какой-то причине что-то вроде std::tuple<std::array<std::array<int, 2>, 2>, ...>({{0, 1}, {2, 3}}, ...) терпит неудачу с «отсутствием ошибки конструктора». Однако он работает в 1D.

std::tuple<std::vector<std::vector<int>>, ...>({{0, 1}, {2, 3}}, ...) фактически делает работу, но векторы, кажется, как избыточна здесь

Любые мысли, SO? Есть ли способ заставить массивы C-стиля работать? Это было бы идеально.

+0

[Это] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4387) может быть актуальным и, по-видимому, ожидается на C++ 17. – Quentin

ответ

7

Вам нужна дополнительная пара скобок {} вокруг массива:

std::tuple<std::array<std::array<int, 2>, 2>, int> v({{{0, 1}, {2, 3}}}, 1); 
                ^   ^

Это происходит потому, std::array инициализируется с использованием совокупного инициализацию. Он работает с std::vector, потому что есть конструктор std::vector<std::initializer_list<T> (std::array не имеет конструкторов).

+0

Вы, конечно, правы. Upvoted. Еще бы хотелось, чтобы C-образные массивы работали. – user2333829

0

Вы можете использовать std::make_tuple, пример:

auto t = std::make_tuple<std::array<std::array<int, 2>, 2>>({{{1, 2}, {3, 4}}}); 

[править] Мое первоначальное предложение было:

auto t = std::make_tuple<int[2][2], int>({{1, 2}, {3, 4}}, 42); 

Но это небезопасно (первый элемент кортежа будет указывать на стек памяти); см. обсуждение ниже.

+0

Это именно то, что я хочу! И это работает. Но это безопасно? Возвращаемый тип: 'std :: tuple '. – user2333829

+1

Мое беспокойство заключается в том, что он возвращает указатели на данные в std :: initializer_list. – user2333829

+2

@ user2333829 Внутренний тип будет 'int (*) [2]', поэтому он небезопасен. Просто попробуйте вернуть это из функции или скопировать такой «кортеж», и вы быстро увидите проблему. – Holt

 Смежные вопросы

  • Нет связанных вопросов^_^