Home > database >  How to pass initializers for the C template class member in the constructor?
How to pass initializers for the C template class member in the constructor?

Time:04-15

Let's say I have following C class

template<uint32_t NUM_OF_POINTS>
class A
{

public:

struct Point {
  float x;
  float y;
};

// here I don't know how to pass the initializers for the private member
  A();

private:

  Point table[NUM_OF_POINTS];

};

I have been looking for a way how I could pass the initializers for the member table via the constructor i.e. I would like to have the ability to do this:

A<4> a({{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}});

Is it ever possible in C e.g. via the variadic templates?

CodePudding user response:

Is it ever possible in C ?

One of the alternatives is to take a parameter of type Point (&&)[NUM_OF_POINTS] then use std::copy to copy the value to the member variable

A(Point (&&arr)[NUM_OF_POINTS]) {
  std::copy(arr, arr   NUM_OF_POINTS, table);
}

Demo

CodePudding user response:

You can take a reference to a C-style array of Points as a parameter and copy-initialize table by means of the indices trick:

#include <cstdint>
#include <utility>

template <std::uint32_t NUM_OF_POINTS>
class A {
   public:
    struct Point {
        float x;
        float y;
    };

    A(Point const (&pts) [NUM_OF_POINTS])
        : A(pts, std::make_index_sequence<NUM_OF_POINTS>{})
    { }

   private:
    Point table[NUM_OF_POINTS];

    template <std::size_t ... I>
    explicit A(Point const (&pts) [NUM_OF_POINTS], std::index_sequence<I...>)
        : table{ pts[I]... }
    {  }
};

This approach doesn't require Point to be default constructible.

You can then construct A as follows:

int main()
{
    A<2>::Point pts[2]{};
    A<2> a (pts);

    A<2> b ({{0,0}, {0,0}});
}

By the way, by making Point dependant from A, you'll have many unrelated point types like A<1>::Point, A<2>::Point, and so on.

  • Related