C++11 Feature Proposal: Delegated constructor

391 views
Skip to first unread message

Mounir Lamouri

unread,
Sep 24, 2014, 6:29:42 AM9/24/14
to Chromium-dev, blin...@chromium.org
What:
Allow use of delegated constructor.

Why:
Improves code readability.

For example:

class Foo {
public:
explicit Foo(int a);
Foo(); // uses a default value for a

private:
int a_;
};

Without this feature, you would have to write:
Foo:Foo(int a) {
Init(a);
}
Foo::Foo() {
Init(kDefaultValue);
}
Foo::Init(int a) {
a_ = a;
}

With the feature enabled, you can write:
Foo::Foo(int a)
: a_(a) {
}
Foo::Foo()
: Foo(kDefaultValue) {
}

Not having to use Init() makes things more readable and more natural. It
also allows the members to be initialized in the initialization list
instead of a function.

-- Mounir

Ryan Sleevi

unread,
Sep 24, 2014, 6:45:28 AM9/24/14
to mou...@lamouri.fr, blink-dev, Chromium-dev


On Sep 24, 2014 3:29 AM, "Mounir Lamouri" <mou...@lamouri.fr> wrote:
>
> What:
> Allow use of delegated constructor.
>
> Why:
> Improves code readability.
>
> For example:
>
> class Foo {
> public:
>   explicit Foo(int a);
>   Foo(); // uses a default value for a

For sake of example/discussion, isn't this just default argument smuggling via a different route (e.g. something the style guide prohibits)?

I realize it's possible to do this today, but the Init() duplication is usually enough of a smell to trigger reviewers' Spidey sense.

>
> private:
>   int a_;
> };
>
> Without this feature, you would have to write:
> Foo:Foo(int a) {
>   Init(a);
> }
> Foo::Foo() {
>   Init(kDefaultValue);
> }
> Foo::Init(int a) {
>   a_ = a;
> }
>
> With the feature enabled, you can write:
> Foo::Foo(int a)
>     : a_(a) {
> }
> Foo::Foo()
>     : Foo(kDefaultValue) {
> }
>
> Not having to use Init() makes things more readable and more natural. It
> also allows the members to be initialized in the initialization list
> instead of a function.
>
> -- Mounir
>

> --
> --
> Chromium Developers mailing list: chromi...@chromium.org
> View archives, change email options, or unsubscribe:
>     http://groups.google.com/a/chromium.org/group/chromium-dev

Note that the current style guide discourages complex work in constructors. The discussions of Init() and its reasonings are complex and lengthy, full of both pros and cons, but am I correct that you would see this as a way to de-Init() things that would otherwise have Init()?

I'm not trying to bait anything - I don't gave strong feelings one way or the other. But I do want to check what the end result may look like, and whether or not we want that.

Hendrik

unread,
Sep 24, 2014, 11:40:47 AM9/24/14
to chromi...@chromium.org, mou...@lamouri.fr, blin...@chromium.org, rsl...@chromium.org
The posted example might be a bit too simple.

Another contrived example:

struct A {
  string a;
  string b;

  A(string a, string b) : a(a), b(b) {}
  A() : a("a"), b("b") {}
};

Using an init function here would cause the string to be constructed empty, then assigned to the desired value -- less efficient.  It would also add another function which isn't needed.

I'm sure everyone here has run into the situation where they created more than one constructor and end up duplicating the default values.  This is error prone, someone may later change the default in one spot and miss the other.

It's hard to argue against using this feature.

+1

On Wednesday, September 24, 2014 3:45:28 AM UTC-7, Ryan Sleevi wrote:

> View archives, change email options, or unsubscribe:
>     http://groups.google.com/a/chromium.org/group/chromium-dev

Viet-Trung Luu

unread,
Sep 24, 2014, 12:08:23 PM9/24/14
to Ryan Sleevi, mou...@lamouri.fr, blink-dev, Chromium-dev
You're right that we shouldn't use delegated constructors to circumvent the rule on default arguments (and we should caution about that), but there are other valid use-cases.

Example 1: constructors for mostly orthogonal cases that nonetheless share some common initialization.
Example 2: delegating to a private constructor, which exists so that friended tests can mock out an internal implementation detail.

(A further advantage of delegated constructors, over e.g. a "CtorHelper()" method, is that it allows more members to be declared const where appropriate.)

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Peter Kasting

unread,
Sep 24, 2014, 7:02:13 PM9/24/14
to Ryan Sleevi, Mounir Lamouri, blink-dev, Chromium-dev
On Wed, Sep 24, 2014 at 3:44 AM, Ryan Sleevi <rsl...@chromium.org> wrote:

For sake of example/discussion, isn't this just default argument smuggling via a different route (e.g. something the style guide prohibits)?

The Google style guide explicitly allows default arguments in constructors.  The cons for default arguments it lists are mostly about what happens to code that takes function addresses and uses function pointers, and "Most of the cons listed above don't apply to constructors because it's impossible to take their address."  (More at http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Default_Arguments .)

Therefore, delegated constructors used to avoid default arguments are just fine, style-guide-wise.

I strongly support delegated constructors.  For classes with const members, using an Init() method to init the members is impossible.  Even for non-const members, most classes' constructors need to do simple work rather than what the style guide defines as complex work -- "call[ing] virtual functions or attempt[ing] to raise non-fatal failures" -- and delegated constructors eliminate copies of that boilerplate.  I've definitely written buggy code multiple times that failed to update all the constructors for a class when adding a member, and delegated constructors would help.

PK

Vitaly Buka

unread,
Sep 24, 2014, 11:43:12 PM9/24/14
to Mounir Lamouri, Chromium-dev, blin...@chromium.org
+1

James Robinson

unread,
Sep 25, 2014, 2:12:26 AM9/25/14
to Ryan Sleevi, Mounir Lamouri, blink-dev, Chromium-dev
On Wed, Sep 24, 2014 at 3:44 AM, Ryan Sleevi <rsl...@chromium.org> wrote:

For sake of example/discussion, isn't this just default argument smuggling via a different route (e.g. something the style guide prohibits)?


Constructors are already somewhat special in terms of the default argument rule since you can't pick the name of the constructor, like you can for other functions.

I think this feature would be pretty useful and don't see any real problems with it.

- James

Maciej Pawlowski

unread,
Sep 25, 2014, 4:17:37 AM9/25/14
to chromi...@chromium.org
One thing a delegated ctor allows that an Init method doesn't is
constructing const members. We could not emulate this behavior with an
Init if the strings 'a' and 'b' were const.

I don't see why we wouldn't want this, can't come up with any real
drawbacks. So +1

W dniu 2014-09-24 17:40, Hendrik pisze:
> The posted example might be a bit too simple.
>
> Another contrived example:
>
> struct A {
> string a;
> string b;
>
> A(string a, string b) : a(a), b(b) {}
> A() : a("a"), b("b") {}
> };
>
> Using an init function here would cause the string to be constructed
> empty, then assigned to the desired value -- less efficient. It would
> also add another function which isn't needed.
>
> I'm sure everyone here has run into the situation where they created
> more than one constructor and end up duplicating the default values.
> This is error prone, someone may later change the default in one spot
> and miss the other.
>
> It's hard to argue against using this feature.
>
> +1
>

--
BR
Maciej Pawlowski
Opera Desktop Wroclaw

Dana Jansens

unread,
Sep 25, 2014, 10:23:36 AM9/25/14
to mpawl...@opera.com, chromium-dev
I know I've wanted this before. For example the 4 constructors of ResourceProvider::Resource could be simpler: https://code.google.com/p/chromium/codesearch#chromium/src/cc/resources/resource_provider.cc&l=209



--
--
Chromium Developers mailing list: chromi...@chromium.org

Colin Blundell

unread,
Sep 25, 2014, 10:27:57 AM9/25/14
to Dana Jansens, mpawl...@opera.com, chromium-dev
I propose that if the Google style guide allows a given C++11 feature that's currently supportable in Chromium across all platforms, the default should be that Chromium supports it. i.e., the argument would have to be made for disallowing it, not for allowing it.

~Colin

Jeremy Roman

unread,
Sep 25, 2014, 11:24:11 AM9/25/14
to Dana Jansens, mpawl...@opera.com, chromium-dev
To me, this seems like a stronger case for in-class member
initializers than delegated constructors. Then you could just say (in
the header):

int child_id = 0;
int gl_id = 0;
// ...

Hendrik

unread,
Sep 25, 2014, 11:36:42 AM9/25/14
to chromi...@chromium.org, dan...@chromium.org, mpawl...@opera.com
I'm not a big fan of in-class member initializers -- and I'll explain why when someone gets around to proposing them.

Don't get me wrong, I don't think they should be banned, but used in limited cases.


On Thursday, September 25, 2014 8:24:11 AM UTC-7, Jeremy Roman wrote:
To me, this seems like a stronger case for in-class member
initializers than delegated constructors. Then you could just say (in
the header):

int child_id = 0;
int gl_id = 0;
// ...

On Thu, Sep 25, 2014 at 10:22 AM, Dana Jansens wrote:
> I know I've wanted this before. For example the 4 constructors of
> ResourceProvider::Resource could be simpler:
> https://code.google.com/p/chromium/codesearch#chromium/src/cc/resources/resource_provider.cc&l=209
>
> On Thu, Sep 25, 2014 at 4:16 AM, Maciej Pawlowski 

Antoine Labour

unread,
Sep 25, 2014, 2:13:09 PM9/25/14
to Dana Jansens, mpawl...@opera.com, chromium-dev
On Thu, Sep 25, 2014 at 7:22 AM, Dana Jansens <dan...@chromium.org> wrote:
I know I've wanted this before. For example the 4 constructors of ResourceProvider::Resource could be simpler: https://code.google.com/p/chromium/codesearch#chromium/src/cc/resources/resource_provider.cc&l=209


In this case (and other similar ones), it easily happens that a field gets added to the struct/class, and some of the constructor's initialization list, but not others.
So +1 to delegated constructors for safety.

Antoine

 
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.

Peter Kasting

unread,
Oct 29, 2014, 4:38:07 PM10/29/14
to Mounir Lamouri, Chromium-dev, blink-dev
It sounds as if support for this varies, but there's no real opposition, and some explicit support from notable owners.

Can we go ahead and put this in the allowed list?

PK

Charlie

unread,
Oct 30, 2014, 3:38:43 PM10/30/14
to chromi...@chromium.org, mou...@lamouri.fr, blin...@chromium.org
+1 let's add this to the C++11 feature whitelist.

James Robinson

unread,
Oct 30, 2014, 3:59:20 PM10/30/14
to Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
On Wed, Oct 29, 2014 at 1:37 PM, 'Peter Kasting' via blink-dev <blin...@chromium.org> wrote:
It sounds as if support for this varies, but there's no real opposition, and some explicit support from notable owners.

Can we go ahead and put this in the allowed list?

Only you can put things on the allowed list :)

Send a patch that moves the feature to the correct place in styleguide/c++/c++11.html *and* uses the feature in some bit of cross-platform code so we can make sure it works and I'll approve it once the trybots are green.

- James

PK

Peter Kasting

unread,
Oct 30, 2014, 4:10:25 PM10/30/14
to James Robinson, Mounir Lamouri, Chromium-dev, blink-dev
Send a patch that moves the feature to the correct place in styleguide/c++/c++11.html *and* uses the feature in some bit of cross-platform code so we can make sure it works and I'll approve it once the trybots are green.\

I'm unfortunately OOO for an extended period due to some broken bones right now, so I'm not in a position to write up this change.  Hopefully some other person is able to do so.

PK 

Charlie Kehoe

unread,
Oct 30, 2014, 5:06:31 PM10/30/14
to pkas...@google.com, James Robinson, Mounir Lamouri, Chromium-dev, blink-dev
I'll see what I can do :-)

--

Charlie Kehoe

unread,
Oct 31, 2014, 12:10:08 PM10/31/14
to Charlie Kehoe, pkas...@google.com, James Robinson, Mounir Lamouri, Chromium-dev, blink-dev
This CL seems to have only unrelated failures:


However our project isn't compiled into bling or clank. I suppose that's not cross-platform enough?

James Robinson

unread,
Oct 31, 2014, 1:53:12 PM10/31/14
to Charlie Kehoe, Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
Something compiled everywhere would be more useful as a first test since those platforms do use different toolchains.

- James

Charlie Kehoe

unread,
Oct 31, 2014, 2:32:21 PM10/31/14
to James Robinson, Charlie Kehoe, Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
Makes sense. I'm a bit new to Chrome though. Can you suggest any particular examples?

James Robinson

unread,
Nov 7, 2014, 1:31:28 PM11/7/14
to Anders Hartvoll Ruud, Charlie Kehoe, Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
Thanks Anders!

- James

On Fri, Nov 7, 2014 at 9:08 AM, Anders Hartvoll Ruud <and...@opera.com> wrote:

Delegated Constructors are now allowed.



To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.


Sami Kyostila

unread,
Mar 6, 2015, 12:05:59 PM3/6/15
to James Robinson, Anders Hartvoll Ruud, Charlie Kehoe, Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
FYI, I ran into an MSVC bug where the compiler silently generates broken code when delegated constructors are used in a diamond virtual inheritance pattern. Apparently the bug has been fixed, but it's still there in MSVC 2013 Update 4. For your sanity, I suggest avoiding delegated constructors in complex inheritance chains for now.

- Sami

Alex Vakulenko

unread,
Mar 6, 2015, 12:18:22 PM3/6/15
to skyo...@google.com, James Robinson, Anders Hartvoll Ruud, Charlie Kehoe, Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
Omg, I can use diamond virtual inheritance? Why did nobody told me this before? (...writing new code frantically...) :)

Hajime Morrita

unread,
Mar 11, 2015, 2:12:06 PM3/11/15
to Sami Kyostila, James Robinson, Anders Hartvoll Ruud, Charlie Kehoe, Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
This bit me today. It was simply daunting to hit this kind of compiler bugs.
Thanks Sami for posting this heads up. I won't decide this being the compiler bug without this report and would be just sobbing silently. 
Lesson learned: In such a big code base, the complex inheritance chains are everywhere ... without having you aware of it.

On Fri, Mar 6, 2015 at 9:05 AM, Sami Kyostila <skyo...@chromium.org> wrote:

Nico Weber

unread,
Mar 11, 2015, 10:38:35 PM3/11/15
to Hajime Morrita, Sami Kyostila, James Robinson, Anders Hartvoll Ruud, Charlie Kehoe, Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
Does anyone have a sense how heavily we use delegated constructors already? If they're so tricky to use (in the sense that they can trigger compiler bugs) that they bit two people within a week, we probably shouldn't allow them yet.

James Robinson

unread,
Mar 23, 2015, 2:25:23 PM3/23/15
to Nico Weber, Hajime Morrita, Sami Kyostila, Anders Hartvoll Ruud, Charlie Kehoe, Peter Kasting, Mounir Lamouri, Chromium-dev, blink-dev
My sense is that diamond virtual inheritance is very rare in Chromium (as it should be, it's banned by the style guide).  If my sloppy git grep is accurate the main-test uses cases are for  content::ChildThread, content::RenderWidget and content::RenderWidgetHost.  There are 2 other uses that don't seem as widely used.  The content ones are definitely complicated but I think we could avoid the delegated constructor issue in these particular places by adding big scary comments in the header files for these.  We should never get new uses of diamond virtual inheritance in chromium and at least the RenderWidget/RenderWidgetHost uses will go away eventually thanks to site isolation (although it's a very long term sort of eventually) so I don't think a general ban is needed.

- James
Reply all
Reply to author
Forward
0 new messages