简体   繁体   中英

how to access a series of const variables as const array

It's clear I can have:

const TYPE a();
const TYPE b();
const TYPE c();

and I can have

const TYPE all[] = {
  TYPE(),
  TYPE(),
  TYPE(),
};

But I would like to have both - direct and array access.

The memory layout should be the same anyway. The idea of a union comes to mind. Something along the lines of:

union FOO {
  struct index_t {
    TYPE a;
    TYPE b;
    TYPE c;
  } index;
  TYPE all[];
};

const FOO foo;
foo.index.a;
foo.all[0];

The naive approach is to just use references in the array

const TYPE a();
const TYPE b();
const TYPE c();

const TYPE all[3] = {
  a,
  b,
  c,
};

The questions is: Can I be sure these are only 3 instances or is there some copying going on turning them into 6? Is there any memory overhead at all?

So which way would be the best to go? Are both approaches feasible?

Note: Of course there is also the option to use an array of pointers - but the goal is to find a way with just references.

An array is a sequence of variables (technically objects, but the distinction is unimportant here). You don't need another one.

TYPE all[3]; // use std::array instead if you can

This is all what's needed . const is of no special importance here, add or remove it as reuired.

Now if you have a craving for syntactic sugar and want to alias all[0] as a etc, this is possible but this possibility is likely to come with a cost.

TYPE &a=all[0], &b=all[1], &c=all[2]; 

The compiler is likely to allocate storage for a, b and c, especially when they are members in a class (that's your cost). It may or may not optimise them away when they are static or automatic variables.

It should be emphasised that a, b and c are not needed . They simply provide alternate names for already existing objects all[i] .

Another way of achieving this is as follows

inline TYPE & a() { return all[0]; } // etc

This is unlikely to have any run-time cost, as compilers are very good at optimising such trivial functions away. The downside is that you need to write a() instead of a .

The union method, even if you manage to get it working for you, is dangerous and not recommended as it necessarily invokes undefined behaviour.

You can have something like:

struct FOO {
    struct INDEX {
        const TYPE a; // Can even initialize in place, e.g. const int a = 8;
        const TYPE b;
        const TYPE c;
    };

    // From here on boilerplate
    Index index;

    FOO() : all{this} {}

    struct ALL {
        ALL(FOO* p): parent{p} {}

        const TYPE& operator[](unsigned index) {
            // Some pointer magic
            return *(static_cast<TYPE*>(static_cast<void*>(parent) + index * sizeof(TYPE)));
        }

        FOO* parent;
    };

    ALL all;
};

You'll have additional memory overhead of only the parent pointer (which is negligible if you plan to have many variables). And there will also be runtime overhead - two static casts, one integer multiplication and one addition, but this will have the access syntax you aim and won't copy the variables.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM