Search code examples
c++arrays

Initilise std::array member in constructor?


I'm looking for a way to initialize a std::array member.

The constructor defines the size of the array. This size is known at compile-time.

Obviously, I can pass the size of the array via a template parameter.

#include <array>

template<size_t x, size_t y>
class MyClass
{
public:
  void memberFunction1();
  void memberFunction2();
  std::array<uint8_t, x*y> m_array;
};

However, the problem here is, that I need to carry the template parameters around in all member functions (this makes things much harder to read).

Is there a way to initialize the array in a constexpr/consteval constructor? So something like that (I could not get it to work though):

#include <array>

class MyClass
{
public:
  std::array m_arr;

  explicit consteval MyClass(const size_t x, const size_t y):
    m_arr{uint8_t, x*y}
  {    
  }
};

I did not choose std::vector or something else, because I'd like to avoid dynamic memory allocation.


Solution

  • You may use CTAD, but need some preparations first:

    template<std::size_t x, std::size_t y>
    struct dims{
        constexpr static std::integral_constant<std::size_t, x> width;
        constexpr static std::integral_constant<std::size_t, y> height;
    }; //dims
    

    Next we can use dims the constructor arguments of our class:

    template<std::size_t x, std::size_t y>
    class my_class{
    public:
        constexpr static dims<x,y> size;
        constexpr my_class(dims<x,y>)/*ctor definition*/;
    private:
        /*rest of my_class*/
    };
    

    Now C++20 provides us the default CTAD mechanism:

    my_class my_object{ dims<my_x,my_y>{} };
    

    Notice that for CTAD, all template arguments must be deducible from constructor parameters. In this example we just had dimensional arguments. If there are other arguments in the class template list, they must also be somehow reflected in constructor arguments. In C++17 you'd need a CTAD directive:

    template<std::size_t x, std::size_t y>
    myclass(dims<x,y>) -> my_class<x,y>;