[llvm-dev] RFC: Strong typedef for LLVM

David Greene via llvm-dev llvm-dev at lists.llvm.org
Thu Aug 1 13:44:50 PDT 2019


Reid Kleckner <rnk at google.com> writes:

> On Thu, Aug 1, 2019 at 9:41 AM Doerfert, Johannes via llvm-dev <llvm-dev at lists.llvm.org> wrote:
>
>  +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


More information about the llvm-dev mailing list