3

I just made a sample, which from my personal point of view should not compile, or at least give a warning, but Visual Studio 2017 does not give any warnings. The sample is following:

#include <stdexcept>

struct Foo {
    Foo(int i) { throw std::runtime_error("Oh no:("); }
    Foo(float f) {}
};

struct Bar {
    Bar() {}
};

struct Baz {
    Baz() : foo(5.0f) {}

    Bar bar;
    Foo foo = Foo(3);
    Bar bar2;
};

int main()
{
    Baz baz;
}

From my point of view (but I am not a language lawyer), the two initializations of foo (in-place vs initializer list) are ambiguous. So what are the rules in this case?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Rudolfs Bundulis
  • 11,636
  • 6
  • 33
  • 71

1 Answers1

7

The value provided in your constructor is explicitly preferred.

[class.base.init]/10: If a given non-static data member has both a default member initializer and a mem-initializer, the initialization specified by the mem-initializer is performed, and the non-static data member's default member initializer is ignored.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • you beat me by 20 seconds :/ – Swordfish May 09 '19 at 15:30
  • That's a standard ref :P – 463035818_is_not_an_ai May 09 '19 at 15:33
  • @user463035818 Cheated a bit because [I already had it ready from within the last month](https://stackoverflow.com/a/55707797/560648) ;) – Lightness Races in Orbit May 09 '19 at 15:35
  • Thanks for the answer, still seems weird that there isn't at least a warning, but hey - that is up to M$. – Rudolfs Bundulis May 09 '19 at 15:45
  • @RudolfsBundulis It's also up to clang and gcc, and they do no such thing either: https://godbolt.org/z/hy_6ki ;) – Max Langhof May 09 '19 at 15:47
  • 1
    @RudolfsBundulis I can't see a reason for a warning, personally. I guess in this contrived example it seems like it may be a programmer mistake, but there are plenty of reasons to want to provide an overrideable default (recall that you may have multiple ctors). Well, one or two reasons, anyway. And then you'd have to disable the warning to shut it up which is ungood. – Lightness Races in Orbit May 09 '19 at 15:57
  • I suppose I'd support a warning that was triggered when _all_ ctors were to "override" a default member initializer, but that's likely more trouble than it's worth (but possibly worth suggesting to the GCC/Clang peeps!) – Lightness Races in Orbit May 09 '19 at 15:59
  • @LightnessRacesinOrbit good point about multiple ctors, I did not consider that, but yeah in this case when "all" (the only one:D) ctors override the in-place, it would be nice. – Rudolfs Bundulis May 09 '19 at 16:05
  • 1
    @RudolfsBundulis • I don't understand why you think there should be a warning. What is there to warn about? – Eljay May 09 '19 at 16:37
  • @Eljay To be fair it's not immediately obvious which initialiser takes precedence (hence this question) and if it looks like a programmer mistake (like in the simplified code in the question) then that's arguably a good enough reason to warn. – Lightness Races in Orbit May 09 '19 at 17:03
  • 1
    @Eljay Ill try to think of good counter examples, but the first that comes to mind - why warn about reordering in initializer list, since you "know" the order of execution from the standard? As mentioned by others, if a person can mistakenly do this and expect the in-line initializer to be used that is a good enough reason to warn imho. This is of course a very border-line example, and I intended to construct it that way, and I totally agree that in case of multiple ctors there should not be a warning. – Rudolfs Bundulis May 09 '19 at 21:02
  • @RudolfsBundulis • If the default member initializer is ignored for all constructors both provided or compiler synthesized, then it is dead code. Yes, I agree that a warning for that situation would be nice. – Eljay May 10 '19 at 12:06