Reid Kleckner <rnk@google.com> writes:
+1, I like this a lot.
Recently, I started to use two element `enum class`es to force people (mostly me)
to spell out what true/false actually means in a certain context. The solution proposed
here comes with more boilerplate but once available it is nicer (I think) and for sure
more generic.
I agree, I think for bools, an enum class is the simplest language
provided way to get most of the benefits that a strong typedef (or
value wrapper class) would provide. I would prefer to keep using them
for these cases, especially for widely used user facing APIs. The less
publicly visible the function is (private method, file local static,
etc), the more inclined I am to just keep doing what we're doing for
expediency and brevity.
This all sounds fine. My implementation of NamedBoolean allows this
kind of thing:
struct AFlag : public NamedBoolean<AFlag> {
using NamedBoolean::NamedBoolean;
};
struct AnotherFlag : public NamedBoolean<AnotherFlag> {
using NamedBoolean::NamedBoolean;
};
AFlag flag1;
AnotherFlag flag2;
if (flag1 || flag2) { // No explicit casts needed
...
};
I don't think that's quite as convenient with `enum class` but maybe
that's a minor point. Both spellings might be useful in different
contexts.
For integer values that are easy to confuse (physical register
numbers, byte quantities, bit quantities, alignments, etc), I agree,
we should be leveraging the type system more than we are. Adding a
strong typedef class to make it easier to make these types with less
boilerplate would be great. See existing prior art for this kind of
stuff in clang::CharUnits.
Thanks for the pointer! It looks like CharUnits has more functionality
than the proposed classes. I intend for these classes to be as simple
as possible to handle common cases. I wouldn't want to see them grow to
implement all of the interfaces required by CharUnits.
I suppose I don't love the name "strong typedef", since it kind of
implies a value judgement that C typedefs are weak, and therefore
worse. They aren't worse, they just aren't well suited to this use
case and have other strengths and weaknesses. I see that the C++ paper
proposes calling these "opaque typedefs". I don't know if that's the
best name, but I prefer that shade of paint. 
OTOH, naming it OpaqueTypedef might give users the mistaken impression
that all of the qualities guaranteed by that proposal are provided by
these utilities. That is almost certainly not the case in general
(equality of sizes, for example).
I also think "opaque" is sort of a strange name. The types aren't
opaque. You can do ordinary operations on them (overloaded operators,
etc.). I tend to think of an "opaque" type as something that I can't
really do anything with except pass to/from some black-box interfaces.
That said, I'm not married to the name. If there is some sort of
consensus around a different name that's great! I don't love the Named*
names but couldn't think of anything better.
-David