首页 > 解决方案 > 使用负数组索引访问前一个成员

问题描述

我想使用负数组索引来访问结构中紧接在该数组之前的相同类型成员。

考虑这种类型的代码:

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];

这在编译时正确地确定test42.

-1不幸的是,clang 会产生一个不受约束的警告。const如果我更改为.gcc 也会这样做constexpr

编写此类代码的正确方法是什么?

以下是我已经知道但不喜欢的方式:

标签: c++arrayspointer-aliasing

解决方案


当我尝试这样做时,clang 和 gcc 似乎完全明白我想要什么

是的,但如果被问到(gcc),它们也会产生一些诊断:

prog.cc:6:33:警告:ISO C++ 禁止匿名结构 [-Wpedantic]
     结构{int b0; 诠释 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";
}

推荐阅读