Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Use the new MOZ_DELETE macro to mark privately-declared, never-implemented methods

40 views
Skip to first unread message

Jeff Walden

unread,
Nov 9, 2011, 5:18:27 PM11/9/11
to
If you find yourself reaching for the private-but-not-implemented idiom to prevent copy-construction and default assignment in classes you write -- e.g. this:

struct S
{
private:
S(const S& other);
void operator=(const S& other);
};

Please also use the new MOZ_DELETE macro in mozilla/Types.h when you do so:

struct S
{
private:
S(const S& other) MOZ_DELETE;
void operator=(const S& other) MOZ_DELETE;
};

This macro encapsulates C++11 deleted function syntax, which causes any use of the corresponding function to be a compile-time (not link-time) error. MOZ_DELETE compiles to the C++11 syntax when possible, and it compiles to nothing if not. Unfortunately only Clang supports this right now, because GCC requires -std=c++0x to support it warning-free, and we don't use -std=c++0x. Anyone want to make GCC support this? *wink* *wink* *nudge* *nudge*

Full details here and here:

http://whereswalden.com/2011/11/09/introducing-moz_delete-a-macro-improving-upon-the-deliberately-unimplemented-method-idiom/
http://hg.mozilla.org/integration/mozilla-inbound/rev/f2184dfdda31

Jeff

Benoit Jacob

unread,
Nov 9, 2011, 11:10:43 PM11/9/11
to Jeff Walden, dev-pl...@lists.mozilla.org
2011/11/9 Jeff Walden <jwald...@mit.edu>:
> If you find yourself reaching for the private-but-not-implemented idiom to
> prevent copy-construction and default assignment in classes you write --
> e.g. this:
>
>  struct S
>  {
>    private:
>      S(const S& other);
>      void operator=(const S& other);
>  };
>
> Please also use the new MOZ_DELETE macro in mozilla/Types.h when you do so:
>
>  struct S
>  {
>    private:
>      S(const S& other) MOZ_DELETE;
>      void operator=(const S& other) MOZ_DELETE;
>  };
>
> This macro encapsulates C++11 deleted function syntax, which causes any use
> of the corresponding function to be a compile-time (not link-time) error.

I don't get this: why would that be a link-time error? If a compiler
doesn't generate a compile-time error already for the first form, it's
buggy. I checked with g++ 4.6.1:

This program:

struct S
{
S() {}
private:
S(const S& other);
void operator=(const S& other);
};

int main()
{
S a;
S b(a);
S c;
c = a;
}

Gives me these compile errors with G++ 4.6.1:

$ g++ a.cpp -o a
a.cpp: In function ‘int main()’:
a.cpp:5:5: error: ‘S::S(const S&)’ is private
a.cpp:12:9: error: within this context
a.cpp:6:10: error: ‘void S::operator=(const S&)’ is private
a.cpp:14:8: error: within this context

Benoit

Joshua Cranmer

unread,
Nov 9, 2011, 11:16:19 PM11/9/11
to
On 11/9/2011 10:10 PM, Benoit Jacob wrote:
> 2011/11/9 Jeff Walden<jwald...@mit.edu>:
>> If you find yourself reaching for the private-but-not-implemented idiom to
>> prevent copy-construction and default assignment in classes you write --
>> e.g. this:
>>
>> struct S
>> {
>> private:
>> S(const S& other);
>> void operator=(const S& other);
>> };
>>
>> Please also use the new MOZ_DELETE macro in mozilla/Types.h when you do so:
>>
>> struct S
>> {
>> private:
>> S(const S& other) MOZ_DELETE;
>> void operator=(const S& other) MOZ_DELETE;
>> };
>>
>> This macro encapsulates C++11 deleted function syntax, which causes any use
>> of the corresponding function to be a compile-time (not link-time) error.
> I don't get this: why would that be a link-time error? If a compiler
> doesn't generate a compile-time error already for the first form, it's
> buggy.
Note that you could still use the non-deleted functions from within
struct S or any friends thereof (but it would fail to find the reference
at link time).

Jeff Walden

unread,
Nov 10, 2011, 4:45:29 AM11/10/11
to
On 11/09/2011 08:10 PM, Benoit Jacob wrote:
> I don't get this: why would that be a link-time error?

What jcranmer said. I was perhaps overly terse in implying it would always be a link-time error -- if it's private and the use is by a non-friend it's compile-time, but if it's a use by a friend it's link-time. Perhaps usually the error will be compile-time, but I have encountered it as a link-time error before, in this hopefully-not-too-tricky-to-grasp instance:

http://hg.mozilla.org/integration/mozilla-inbound/rev/85f790b1de47

When could an error be correctly reported if I had not changed the assert in JSLinearString::chars() from |isLinear()| to |JSString::isLinear()|? Only at link time, due to the possibility that I might have defined a |JSLinearString::isLinear()| out-of-line at some later time.

Jeff

Rafael Ávila de Espíndola

unread,
Nov 10, 2011, 4:50:26 PM11/10/11
to dev-pl...@lists.mozilla.org
> This macro encapsulates C++11 deleted function syntax, which causes any
> use of the corresponding function to be a compile-time (not link-time)
> error. MOZ_DELETE compiles to the C++11 syntax when possible, and it
> compiles to nothing if not. Unfortunately only Clang supports this right
> now, because GCC requires -std=c++0x to support it warning-free, and we
> don't use -std=c++0x. Anyone want to make GCC support this? *wink*
> *wink* *nudge* *nudge*

We use -std=gnu++0x, does it warn with it?

https://tbpl.mozilla.org/php/getParsedLog.php?id=7329403&tree=Firefox&full=1

> Jeff

Cheers,
Rafael

Jeff Walden

unread,
Nov 11, 2011, 1:15:27 AM11/11/11
to
I just landed a followup change in mozilla-inbound to make MOZ_DELETE work with gcc, at least when compilation is occurring with -std=c++0x. It turns out we do use this fairly often on most platforms (the big exception being that the JS engine doesn't use it), so this actually does provide a fair bit of benefit to gcc users. Still, it's probably best to use clang if you want MOZ_DELETE to always be fully effective, no exceptions, even in the JS engine or in "exotic" situations like compiling with particular Android SDKs or somesuch.

Jeff

Jeff Walden

unread,
Nov 11, 2011, 1:26:04 AM11/11/11
to
On 11/10/2011 01:50 PM, Rafael Ávila de Espíndola wrote:
> We use -std=gnu++0x, does it warn with it?
>
> https://tbpl.mozilla.org/php/getParsedLog.php?id=7329403&tree=Firefox&full=1

gcc doesn't warn about =delete with that in place. And thanks to some advice from glandium, gcc now uses =delete when it can (including with gnu++0x. So I think we're set here as far as gcc goes. (Although if we just always built with -std=c++0x, or gnu++0x, or what-have-you, that would be best, of course. But that wish is far afield from any desires to use deleted function syntax, warning-free, in gcc.)

Jeff
0 new messages