0

I have for example the following code:

#include <iostream>
#include <array>

class Base {
public:
  Base() : mA(std::array<int,2>()) {}
  Base(std::array<int,2> arr) : mA(arr) {}
  Base(/* what to write here ??? */);
private:
  std::array<int,2> mA;
};

int main() 
{
    std::array<int,2> a = {423, 12}; // Works fine
    Base b(a); // Works fine
    Base c({10, 20}); // This is what I need. 

    return 0;
}

How should I define constructor to allow initialization with as shown in the 3rd line inside "main" above? In general, I need a configurable (in length in compile / run time) structure that will allow initialization with list of numbers, like {1, 2, 3} or (1, 2, 3) or something similar without need to element-by-element copying. I chose std::array for simplicity, but I'm afraid it might not work with this kind of initialization. What container would your recommend?

Thanks, Kostya

mkostya
  • 922
  • 3
  • 10
  • 14
  • I don't think it's possible with using the `{` and the `}` because such type of initialization it's a language feature rather than a function or something, so you can't "emulate" it – SingerOfTheFall Nov 07 '12 at 09:06
  • It's interesting to note that 'Base c({10, 20});' works with GCC 4.8 (didn't work with 4.7) and Clang 3.4. – Ricky65 Jan 27 '14 at 14:17

1 Answers1

5

You could add a constructor that takes an std::initializer_list<int> and copy the contents into the array:

#include <initializer_list>
#include <algorithm>

....

Base(std::initializer_list<int> a) {
   // check size first
   std::copy(a.begin(), a.end(), mA.begin()); }
}

Note: If you wanted to hold a number of elements defined at runtime, then you should use a an std::vector<int> This has a constructor from initializer_list<int> so the code is simpler:

class Foo {
public:
  Foo() {}
  Foo(const std::vector<int>& arr) : mA(arr) {}
  Foo(std::initializer_list<int> a) : mA(a) {}
private:
  std::vector<int> mA;
};

You can initialize it like this:

Foo f1({1,2,3,4,5});

or

Foo f2{1,2,3,4,5};
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • the `mA` member array is fixed to the size `2`, so IMHO the ctor must check if the initializer list is if the size `2`, or take only the `2` first members or do some other check. What would do `std::copy` if `mA` isn't big enough to fit the initializer list? – PaperBirdMaster Nov 07 '12 at 09:19
  • In this case, will I be able to initialize it with number list {1, 2, 3} ? – mkostya Nov 07 '12 at 09:20
  • @mkostya You should check that the siye of the initializer_list is the same as that of the array. In your case, initializing with 3 elements is an error, because the array is of size 2. – juanchopanza Nov 07 '12 at 09:22
  • @mkostya I added an example with dynamic size. – juanchopanza Nov 07 '12 at 09:28
  • The example with dynamic size is good, correct and nice. But the original code works with a fixed size array; if the class design is limited to fixed size (for some unknown reason) i think that the fixed size and type of container must be preserved. – PaperBirdMaster Nov 07 '12 at 09:32
  • @juanchopanza Thank you very much! It worked, I also added a check on list size. – mkostya Nov 07 '12 at 09:41
  • @juanchopanza Thanks also for the example with dynamic size. However, the code should work with constant-size groups of numbers, and the constant is known in compile time (it will be configured with a template parameter). I preferred std::array as it looks like more compact than std::vector, which can do a lot of things which I don't need. In terms of initialization run-time, I think initializing std::vector from std::initializer_list involves copying of elements anyway, so there should not be run time diff between two . – mkostya Nov 07 '12 at 09:46