Question

Well, maybe from the title is not clear what I'm actually asking.

I have a class with an initializer-list constructor std::initializer_list<B>. Is legal initialize it with an initializer list of objects of class D, where D is derived from B?

#include <initializer_list>

struct B {
    B(int) {}
};

struct D: public B {
    D(int s): B(s) {}
};

struct Foo {
    Foo(std::initializer_list<B> l) {}
};

void main() {
    Foo    f{ D{ 1 }, D{ 2 } };
}

If is not legal, is that ill-formed? or just undefined behavior?

I've tried that code in Visual Studio 2013 Update 1. It compiles, but when I run it, I can see (debugging) how:

  1. An object of class D is created for the first object D{1} (let call tempD1). D constructor is invoked and then the B constructor.
  2. The base of tempD1 is moved to a new B object (tmpB1): B move constructor is invoked.
  3. The same for the second object D{2} (tmpD2, tmpB2).
  4. Foo initializer-list constructor is invoked. All fine at this point.
  5. destructor of tmpB2 is invoked once.
  6. destructor of tmpD2 is invoked twice.
  7. destructor of tmpD1 is invoked once.

I guess is a bug of the compiler (calling one destructor twice and missing the other one). But I'm not sure if that use of std::initializer_list is legal yet.

(Fixed the confusions about 'D' or 'A' name)

Was it helpful?

Solution

The conversion from std::initializer_list<D> to std::initializer_list<B> is not valid... But construct a std::initializer_list<B> with some D is valid (and it is what happens here)...

But you will have object slicing

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top