Я хотел бы использовать отрицательный индекс массива для доступа к члену того же типа, который непосредственно предшествует этому массиву в структуре.
Рассмотрим этот тип кода:
union hello {
int a[2];
struct { int b0; int b1[1]; };
};
Я хочу использовать b1[-1]
чтобы получить доступ b0
,
Когда я пытаюсь это сделать, кажется, что clang и gcc точно понимают, чего я хочу.
extern const int test = hello{{42, 1337}}.b1[-1];
Это правильно определяет во время компиляции, что test
действительно 42
,
К сожалению, Clang выдает предупреждение, что -1
не связан. Gcc делает тоже, если я изменяю const
в constexpr
,
Как правильно написать этот тип кода?
Вот способы, которые я уже знаю, но не люблю:
a[]
с индексированием на основе 1.b1
указатель, который указывает на a[1]
,Если я правильно понимаю ваш вопрос, у вас есть переменные {c0, с1, с2, с3,…}, а иногда вы хотите рассматривать их как массив [c1, с2, с3,…], в другое время как массив [c0, с1, с2, с3,…].
(Я не уверен, что понимаю Зачем Вы хотите сделать это, но не берите в голову.)
Вот одно из решений:
int A[5];
int *B = A+1;
A[0] = c0;
A[1] = c1;
A[2] = c2;
....
Теперь вы можете перебрать A [i], если хотите включить c0, и над B [I], если вы этого не сделаете.
Когда я пытаюсь это сделать, кажется, что clang и gcc точно понимают, чего я хочу
Да, но они также генерируют некоторую диагностику, если их спросить (gcc):
prog.cc:6:33: предупреждение: ISO C ++ запрещает анонимные структуры [-Wpedantic] struct {int b0; int b1 [1]; };
Кроме того, доступ к b1
который не является активным членом союза (a
является инициализированным) является неопределенным поведением.
Вместо этого вы можете написать класс, который инкапсулирует данные и логику требуемого доступа:
#include <iostream>
#include <array>
template<size_t Dim>
class Hello
{
std::array<int, Dim> data_;
public:
template<class... ArgType>
constexpr Hello(ArgType... args) : data_{args...} {};
constexpr int first() const noexcept { return data_[0]; }
constexpr int one_based(int i) const { return data_.at(i + 1); }
constexpr int zero_based(int i) const { return data_.at(i); }
};
int main()
{
constexpr Hello<2> hi {42, 1337};
static_assert(hi.first() == 42);
static_assert(hi.one_based(-1) == 42);
static_assert(hi.one_based(0) == 1337);
static_assert(hi.zero_based(0) == 42);
static_assert(hi.zero_based(1) == 1337);
std::cout << "So far, so good...\n";
}