2

I have some code which effectively reduces to

#include <vector>
class A {
    std::vector<int> m_sizes;
public:
    A(std::initializer_list<int> const& sizes) : m_sizes(sizes) {}
};

class B {
    A m_a;
public:
    B(int size_front, int size_back, std::initializer_list<int> const& sizes) : m_a({ size_front, sizes, size_back }) {}
};

The compiler complains that no instance of A::A matches the argument list. Is there some way to flatten out the { int, std::initializer_list<int>, int } to a std::initializer_list<int> or do I have to give A an extra constructor to handle this situation? What if I couldn't modify the A class?

Rama
  • 3,222
  • 2
  • 11
  • 26
Brett Ryland
  • 1,045
  • 1
  • 9
  • 17
  • 2
    A `std::initializer_list` is not modifiable. This template is mostly for compiler's own use. The only way to initialize a new `std::initializer_list` is with a default constructor, producing an empty list, or with a braced constant. In this case, `A` needs another constructor that takes a `vector` parameter, and uses that to initialize `m_sizes`; then you can use that constructor. If you cannot modify the `A` class, nothing can be done. C++ doesn't work that way. – Sam Varshavchik Feb 07 '17 at 11:53

1 Answers1

2

What you are trying to do is not possible: initializer_list<T> must be constructed from a list of items of type T, whose count is known at compile time. Inserting an existing list in the middle does not work.

You can work around this problem by adding a constructor overload that takes a vector<int> directly, and forwarding calls to it:

class A {
    std::vector<int> m_sizes;
public:
    A(const std::vector<int>& sizes) : m_sizes(sizes) {}
    A(std::initializer_list<int> const& sizes) : A(std::vector(sizes)) {}
};
class B {
    A m_a;
    std::vector<int> frame(int size_front, int size_back, std::initializer_list<int> const& sizes) {
        std::vector res;
        res.push_back(size_front);
        std::copy(sizes.begin(), sizes.end(), std::back_inserter(res));
        res.push_back(size_back);
        return res;
    }
public:
    B(int size_front, int size_back, std::initializer_list<int> const& sizes) : m_a(frame(size_front, size_back, sizes)) {}
};
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Hmmn.... I smell copy-paste mistake?.... Check the order of types of the parameters in the member function `B::frame()`, and what you passed in the *member-initialization-list* in `B`'s constructor – WhiZTiM Feb 07 '17 at 12:20
  • @WhiZTiM You are absolutely right, thank you very much! – Sergey Kalinichenko Feb 07 '17 at 12:53