Implementing flexible array elements with templates and a base class

In C99, you usually see the following pattern:

struct Foo {
    int var1;
    int var2[];
};

Foo * f = malloc(sizeof(struct Foo) + sizeof(int)*n);
for (int i=0; i<n; ++i) {
    f->var2[i] = p;
}

But this is not only bad C ++, but also illegal.

You can achieve a similar effect in C ++ as follows:

struct FooBase {
    void dostuff();

    int var1;
    int var2[1];
};

template<size_t N>
struct Foo : public FooBase {
    int var2[N-1];
};

Although this will work (in FooBase methods you can access var2[2], var2[3]etc.), it relies on Foolike a standard layout, which is not very pretty.

The advantage of this is that a non-templated function can be obtained by anyone Foo*without conversion, taking FooBase*both the calling methods that work on var2and the memory are all contiguous (which may be useful).

Is there a better way to achieve this (which is legal C ++ / C ++ 11 / C ++ 14)?

( ).

+1
6

, , , , ++, struct struct.

, std::vector - , , , .

. .

"" .

struct tag1_t {} tag1;
struct tag2_t {} tag2;
typedef std::tuple< std::pair< tag1_t, int >, std::pair<tag2_t, double> > header_t;

, " , ". , :

struct arr_t {} arr;
std::tuple< header_t, std::pair< arr_t, std::string > > full_t;

- mojo, , N , , int double, N std::string, . .

, , , . , , , .

, , , tuple s, reinterpret_cast , ( const, const).

, operator[], .

, std::vector , boost::mpl , , , , . , , ( ).

Foo* my_data = Foo::Create(7);
my_data->get<tag1_t>(); // returns an int
my_data->get<tag2_t>(); // returns a double
my_data->get<arr_t>()[3]; // access to 3rd one

:

Foo* my_data = Foo::Create(7);
int x = my_data^tag1; // returns an int
double y = my_data^tag2; // returns a double
std::string z = my_data^arr[3]; // access to 3rd std::string

, , .

, , , ++/C ++, , " ". ( , : , operator^ , ).

, , , , ++, , .

+5

C ++.

new char[...]:

struct Foo {
    int var1;
    int var2[1];
};

Foo* foo_ptr = reinterpret_cast<Foo*>(new char[sizeof(Foo) + sizeof(int) * (n - 1)]);

, , , :

delete[] reinterpret_cast<char*>(foo_ptr);

. ( ) , , - ( ). / "" ++ std::vector .

+1

, , ++. , sizeof (T) , . , ++ . , , . , . (alloca ). C , .

++. , sizeof ++, sizeof . , ++, . std::vector .

, constexpr ++ 11 - .

0

, , sugestion :

template<size_t N>
struct Foo {
    int var1;
    std::array<int,N> var2;
};

std::array int v[N]; ( ),

0

, C ( ):

#include <cstdlib>
#include <iostream>

using namespace std;

template <typename T>
class Flexible 
{
public:
   Flexible(){}
   ~Flexible(){}
   inline T & operator[](size_t ind){
      return reinterpret_cast<T*>(this)[ind];
   }
   inline Flexible<T> * getThis() { return this; }
   inline operator T * () { return reinterpret_cast<T*>(this); }
};

struct test{
   int a;
   Flexible<char> b;
};

int main(int argc, char * argv[]){
   cout << sizeof(test) << endl;
   test t;
   cout << &t << endl;
   cout << &t.a << endl;
   cout << &t.b << endl;
   cout << t.b.getThis() << endl;
   cout << (void*)t.b << endl;
   test * t2 = static_cast<test*>(malloc(sizeof(test) + 5));
   t2->b[0] = 'a';
   t2->b[1] = 'b';
   t2->b[2] = 0;
   cout << t2->b << endl;
   return 0;
}

( GCC clang clang++ -fsanitize=undefined, , , reinterpret_cast...)

. , . , , , --... --, . , struct/class , Flexible, , :

class A{
  Flexible<char> a;
};

class B{
  A a;
};

:

class B{
  A a;
  int i;
};
0

late person #X, , ( ).

, "" ? ( [] [0] [1])?

, -, - , - , - , ?

  struct rectangles {
      int8_t depth        ;
      int8_t mode         ;
      rect_  rectz[65536] ;
  } ;

" " - . , , [1] .

0

All Articles