Учитывая эту структуру:
struct Foo {
std::array<int, 8> bar;
};
Как я могу получить количество элементов массива bar
, если у меня нет экземпляра Foo
?
Учитывая эту структуру:
struct Foo {
std::array<int, 8> bar;
};
Как я могу получить количество элементов массива bar
, если у меня нет экземпляра Foo
?
Вы можете использовать std::tuple_size
:
std::tuple_size<decltype(Foo::bar)>::value
std::tuple
s (std::tuple_size
, std::tuple_element
, std::get
), имеют удобную специализацию для обработки std::array<T, N>
как std::tuple<T, T, ..., T>
.
- person Quentin; 27.12.2016
Несмотря на хороший ответ @Jarod42, вот еще одно возможное решение, основанное на decltype
, которое не использует tuple_size
.
Он следует минимальному рабочему примеру, который работает в C++11:
#include<array>
struct Foo {
std::array<int, 8> bar;
};
int main() {
constexpr std::size_t N = decltype(Foo::bar){}.size();
static_assert(N == 8, "!");
}
std::array
уже имеет функцию-член constexpr с именем size
, которая возвращает искомое значение.
constexpr
, в этом смысле std::tuple_size
является лучшим ответом, потому что он не требует никакого строительства или разрушения в не-constexpr
случай.
- person Mgetz; 27.12.2016
std::tuple_size
является лучшим выбором. Тем не менее, я бы, вероятно, сделал using array_size = std::tuple_size
для удобства чтения.
- person Mgetz; 27.12.2016
std::move
, которая ничего не перемещает. Что еще? :-) (примечание: просто шучу)
- person skypjack; 27.12.2016
Вы можете дать Foo
public static constexpr
участника.
struct Foo {
static constexpr std::size_t bar_size = 8;
std::array<int, bar_size> bar;
}
Теперь вы знаете размер столбца из Foo::bar_size
, и у вас есть дополнительная возможность называть bar_size
чем-то более описательным, если Foo
когда-либо имеет несколько массивов одинакового размера.
static const
, я не считаю это хорошим ответом.
- person Tas; 28.12.2016
static constexpr
на самом деле не то, на что можно жаловаться; он не будет занимать места в экземплярах и будет полностью оптимизирован в своей единице перевода (если только его адрес не будет взят, но тогда это потребует внестрочного определения).
- person underscore_d; 29.12.2016
static constexpr
— магическое число. Это решение удаляет магическое число и решает проблему одной простой строкой.
- person Willy Goat; 31.12.2016
Вы можете сделать это так же, как и для устаревших массивов:
sizeof(Foo::bar) / sizeof(Foo::bar[0])
std::extent
, но это не ответ, так как этот все равно потребуется построить экземпляр.
- person Mgetz; 27.12.2016
sizeof std::array<int, 4>
может не совпадать с sizeof int[4]
, это детали реализации. Кроме того, если вы собираетесь создать std::array
, просто используйте size()
член
- person Mgetz; 27.12.2016
sizeof(Foo::bar) / sizeof(Foo::bar[0])
. Не требуется экземпляр Foo.
- person Waxrat; 27.12.2016
std::array
не означают, что в действительности он должен иметь тот же размер и макет, что и необработанный массив, даже если это явно не требуется?
- person underscore_d; 27.12.2016
std::array
все равно имеет член size()
.
- person Mgetz; 28.12.2016
Использовать:
sizeof(Foo::bar) / sizeof(int)
#include <iostream> #include <array> using namespace std; struct Foo { std::array<int, 8> bar; }; int main() { cout << sizeof(Foo::bar) / sizeof(int) << endl; cout << std::tuple_size<decltype(Foo::bar)>::value << endl; return 0; }
- person Gilson PJ; 27.12.2016
Вы можете использовать как:
sizeof Foo().bar
sizeof
- person max66; 27.12.2016
sizeof
не оценивает свой операнд, вы всегда можете просто std::declval<Foo>()
.
- person Angew is no longer proud of SO; 27.12.2016
std::array
может иметь отступы
- person M.M; 27.12.2016
std::array
реализацией, которая делала отступы. Но вы правы.
- person Angew is no longer proud of SO; 27.12.2016
sizeof(Foo::bar)
возвращает размер в байтах вместо количества элементов. Я внесу ясность в вопрос. - person ChronoTrigger   schedule 27.12.2016std::array
отличается? - person max66   schedule 27.12.2016std::array
- это контейнер фиксированного размера. Это то же самое. Моя проблема с вашим предложением заключается не в устранении магического числа (что отлично), а в использовании для этого макроса. - person StoryTeller - Unslander Monica   schedule 27.12.2016std::array
не уменьшается и не растет. Всегда будет 8 построенных объектов. - person StoryTeller - Unslander Monica   schedule 27.12.2016Foo().bar.size()
. Q был бы более интересным, если бы у Foo не было конструктора по умолчанию - person M.M   schedule 27.12.2016std::array
имеет фиксированный размер. - person max66   schedule 27.12.2016std::array<int, 8>
, у вас когда-нибудь будет контейнер с 8 элементами; вы можете установить значение 4 из этих элементов (после инициализации), но остальные 4 присутствуют с начальным значением - person max66   schedule 27.12.2016std::vector<int>
, где вы можетеreserve()
размер для 8 элементов и поместить в него только 4. - person max66   schedule 27.12.2016