Generating Structures dynamically at compile time

坚强是说给别人听的谎言 提交于 2019-11-29 16:06:08

For the second case, I'd usually prefer a typedef that restricts the hackery to one place:

#if SOME_CONSTANT > SOME_VALUE
    typedef uint8_t always_type;
#else
    typedef uint16_t always_type;
#endif

Then the rest of your code will just use always_type throughout:

struct MyStruct {
    // ...
    always_type always_here_but_different_size;
    // ...
};

If you want to use:

typedef std::conditional<(SOME_CONSTANT > VALUE), uint8_t, uint16_t>::type always_type;

That's fine too -- the point here isn't about the syntax you use to get the type you want, but the fact that you generally want to create a name for that type so you can use it where needed.

As for the situation of something being present or not, it's a little hard to say. Typically, such a thing will relate to enabling/disabling certain features at build time. If so, it appears that the class has responsibilities related both to the feature(s) that can be enabled/disabled, and to something else as well. That sounds like it's probably violating the single responsibility principle, and may not be very cohesive. If that's the case, it may indicate a problem that's better addressed at the level of the overall design, than simply the syntax you use.

Caveat: I'm probably extrapolating quite a bit from admittedly minimal evidence -- possibly more than the evidence really supports.

Second case may be replaced by

std::conditional<(SOME_CONSTANT > SOME_VALUE), uint8_t, uint16_t>::type
alywasHereButDifferentSize;

First i think no.

I've seen this done with a union (http://www.cplusplus.com/doc/tutorial/other_data_types/), but I'm unsure about the specifics as I've never implemented it myself. Instead of the second piece of macrohackery, you would have:

union {
  uint8_t alywasHereButDifferentSize;
  uint16_t alywasHereButDifferentSize;
}

and when referencing, you would have an if that referred to one or the other variable.

Alternatively, you could make a void * pointer that you initialise during runtime to a variable of either type.

For the first:

template <bool>
struct implement_maybe_here
{};

template <>
struct implement_maybe_here<true>
{
    int maybe_here;
};

struct my_struct : implement_maybe_here<HAS_MAYBE_HERE>
{
    double always_here;
};

I don't recommend this in any way, since it is difficult to maintain and the maybe_here variable is difficult to initialize (but with any approach, this will be a mess anyway).

Note that you are not guaranteed that implement_maybe_here<false> will take zero memory, however many compilers implement this "empty base optimization".

Use std::conditional for the second one, as @ForEveR suggests.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!