Roman Roman - 3 months ago 12
C++ Question

initializer_list for arrays with predefined sizes

So let's imagine we want to use c++'s initializer_list for some user-defined type that represents array of predefined size (know at compile time). For example matrix's indexes (row,column):

#include <initializer_list>
#include <algorithm>
#include <assert.h>

using idx_t = unsigned;

class MatrixIdx {
public:
MatrixIdx() :
_idx { 0, 0 }
{}

// this is how I'm able to use initializer list for now
// cons:
// * run-time assertion
// * additional header (algorithm)
// * not in member initializer list (call me perfectionist)
//
MatrixIdx(std::initializer_list<idx_t> l)
{
assert(l.size() == 2);
std::copy(l.begin(), l.end(), _idx);
}

//I want to achive constructor similiar to this one
//Won't compile
//
//MatrixIdx(std::initializer_list<idx_t> l) :
//static_assert(l.size() == 2, "two elements expected") //compile time assertion
//_idx[0] ( l[0] ),
//_idx[1] ( l[1] )
//{}

idx_t row() { return _idx[0]; }
void setRow(const idx_t i) { _idx[0] = i; }

idx_t col() { return _idx[1]; }
void setCol(const idx_t i) { _idx[1] = i; }

private:
idx_t _idx[2];
};

int main(void)
{
MatrixIdx idx; //default - OKAY

//MatrixIdx idxIL { 1, 2 }; //this should compile

//this should emit human-readable compile-time error
//MatrixIdx idxILError { 1, 2, 3 };

return 0;
}


What will be the best possible way to achieve this?

Answer

The uniform initialization syntax can be adopted very simply for your situation, just by providing a constructor that accepts two arguments of type idx_t.

class MatrixIdx {
public:
  ...
  MatrixIdx() : ... {}
  MatrixIdx(idx_t, idx_t) : ... {}
};

And in your main code:

int main()
{
  MatrixIdx mat {}; // Okay
  MatrixIdx mat {1,2}; // Okay
  MatrixIdx mat {1,2,3}; // Error - no 3-arg. c'tor for MatrixIdx
}