0

I want to create an array of struct objects that each contain a member which holds a value. However, this value might differ in its type from object to object. As the size can't vary I decided to put a placeholding buffer in the base class which I try to alias from a templated-to-type derived class. But this doesn't work:

#include <iostream>
#include <string>

struct some_struct_base
{
    std::string name_;
    char placeholder_[sizeof(std::string)];
    some_struct_base* next_;
    some_struct_base* prev_;
};

template <typename T>
struct some_struct : some_struct_base
{
    using val = static_cast<T>(some_struct_base::placeholder_);
};


int main()
{
    std::cout << sizeof(some_struct<std::string>) << std::endl;

    some_struct_base arr[10]; // <-- this is why the size needs to be fixed
    std::cout << static_cast<some_struct<std::string>>(arr[10]).val << std::endl; // <-- allow this
}

yields:

<source>:99:17: error: expected type-specifier before 'static_cast'
   99 |     using val = static_cast<T>(some_struct_base::placeholder_);
      |                 ^~~~~~~~~~~

I can halfway understand this as val defines a type and not a variable name. But I don't want to introduce new members to the derived class (like a reference member e.g.) because this needs to run on embedded systems and another 4 bytes is already asking for too much.

How can I achieve this using minimal space / no additional overhead?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
glades
  • 3,778
  • 1
  • 12
  • 34
  • Make `val` a reference that you initialize in a constructor? – Some programmer dude May 11 '22 at 09:15
  • @Someprogrammerdude This adds 4/8 bytes. There should be another way. – glades May 11 '22 at 09:17
  • Then the only solution I can think of is a getter function. Or rethink the design so you don't need the alias. – Some programmer dude May 11 '22 at 09:27
  • 1
    Why don't you just create a function as `T* val() { return static_cast(some_struct_base::placeholder_); }` ? So you don't need any tricky extra variable. And the compiler can easily inline it resulting in 0 overhead at runtime. BUT! it is possible that you will need `reinterpret_cast` since it is possible that you cannot cast `char*` to the requested `T` type... – simre May 11 '22 at 11:36
  • @simre That's a good idea but how do I write to val? – glades May 11 '22 at 12:58
  • 1
    @glades `*(object.val()) = ` OR probably you can dereference in the `val()` function so you get a reference instead of a pointer but I'm not 100% that it'll work... BUT! you must be careful! Since you are using a char[] buffer, you will have to construct the string for example in place, and then destruct since it has no trivial default constructor or destructor!!! – simre May 11 '22 at 13:08

0 Answers0