RFC: Introduce a section to the programmers manual about type hierarchies, polymorphism, and virtual dispatch.

The proposed addition to ProgrammersManuel.rst is below the break…

This is essentially trying to explain the emerging design techniques being used in LLVM these days somewhere more accessible than the comments on a particular piece of infrastructure. It covers the “concepts-based polymorphism” that caused some confusion during initial reviews of the new pass manager as well as the tagged-dispatch mechanism used pervasively in LLVM and Clang.

Perhaps most notably, I’ve tried to provide some criteria to help developers choose between these options when designing new pieces of infrastructure.

Many thanks to Richard Smith who helped me crystalize this, as well as Eric, Dave, and Nick who helped me talk it through.

You can find the actual patch and make comments on Phabricator here: http://reviews.llvm.org/D7191

I’m just going to paste the text below however as I think that’ll more easily facilitate discussion!

Hi all,

I am curious about the proposed invocation traits (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3866.html) and life would be a lot easier if they would make it into the next C++ standard (at least for me). However 201z is far away and I was wondering if someone is already working on this in clang. If not can someone direct me to the right spot in clang where such a feature would be in the right place?

Cheers,
Michael Haidl

I'm not sure what happened, they appear to have made it to N3908, then to N4023, then to N4081 but they don't appear in N4270.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/

Ben

They're hiding here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4335.html

Ben

Given we have a large number of compiler authors and contributors to the C++ language spec, it seems really odd to me that we can't solve this problem in a more elegant way. The tagged-dispatch as a sealed world replacement for virtual dispatch is one that comes up on a pretty regular basis. Might it be time to figure out how to generalize this and propose either a clang extension or a language mechanism for some future version of C++?

Philip

In other words, they’ll appear in libc++.
[ We’re trying to get a full LFTS implementation in there, but it’s not all there yet ]

— Marshall

Thanks for the clarification. I am looking forward to it.
-MH

One of the motivations for being able to mark a class as final in Java was to allow compilers to perform optimisations on the assumption that there would never be any subclasses (I don't believe any modern JVMs take advantage of this as it's mostly only useful to AoT compilers, but maybe ART does). For this idiom, the guarantee that you want is something slightly broader than final, it's that, at some known point, all subclasses will be visible to the optimiser. This is a bit difficult to do in the files-are-approximately-compilation-units model, but a bit easier with LTO (though re-inferring enough information to do devirtualisation at this level is a bit tricky).

C++, at the language level, unfortunately has no notion of a shared library. This is very problematic in some places in C++11 (the semantics for when constructors and destructors are run for thread_local objects in the presence of multiple threads and library loading and unloading are very poorly defined) and also makes it difficult to have a package-final or similar to indicate that no subclasses outside of this library are permitted.

Or, if the goal is to put a little bit more burden on the programmer but give greater flexibility in implementations, I believe that one of the people in this thread is the head of the reflection subcommittee in WG21, so may already be reviewing proposals that would make it easier to implement generically...

David

It might be useful to look at how Apple’s ‘Dylan’ language does this. It’s all been defined and implemented and in use by the (admittedly small) community for 15 - 20 years. CMU’s ‘d2c’ compiler, in particular, uses these to produce code with speed almost indistinguishable from C.

A ‘sealed’ class is precisely one that can not have subclasses defined outside of its library (compilation unit)

http://opendylan.org/books/drm/Declaring_Characteristics_of_Classes

Define Sealed Domain may also be of interest:

http://opendylan.org/books/drm/Define_Sealed_Domain

We should figure out what intrinsics you guys want in order to support
this. I believe it's straightforward to implement invocation_type in terms
of raw_invocation_type in the library, so I think providing simply a
__raw_invocation_type(Fn, Arg1, Arg2, ...) would work?

Looking at N4335 now, I'm a little concerned that we may be standardizing a
bad interface; we don't support using raw_invocation_type<F(Args...)> if F
is a function type, because that would create a function type whose return
type is a function type, which is ill-formed.

Hi all,

I am curious about the proposed invocation traits
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3866.html) and
life would be a lot easier if they would make it into the next C++
standard (at least for me). However 201z is far away and I was wondering
if someone is already working on this in clang. If not can someone
direct me to the right spot in clang where such a feature would be in
the right place?

I'm not sure what happened, they appear to have made it to N3908, then
to N4023, then to N4081 but they don't appear in N4270.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/

They're hiding here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4335.html

In other words, they’ll appear in libc++.
[ We’re trying to get a full LFTS implementation in there, but it’s not
all there yet ]

We should figure out what intrinsics you guys want in order to support
this. I believe it's straightforward to implement invocation_type in terms
of raw_invocation_type in the library, so I think providing simply a
__raw_invocation_type(Fn, Arg1, Arg2, ...) would work?

(And it's up to you whether you'd prefer these arguments to be expressions
or types...)

Hi all,

I am curious about the proposed invocation traits
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3866.html) and
life would be a lot easier if they would make it into the next C++
standard (at least for me). However 201z is far away and I was wondering
if someone is already working on this in clang. If not can someone
direct me to the right spot in clang where such a feature would be in
the right place?

I'm not sure what happened, they appear to have made it to N3908, then
to N4023, then to N4081 but they don't appear in N4270.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/

They're hiding here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4335.html

In other words, they’ll appear in libc++.
[ We’re trying to get a full LFTS implementation in there, but it’s not
all there yet ]

We should figure out what intrinsics you guys want in order to support
this. I believe it's straightforward to implement invocation_type in terms
of raw_invocation_type in the library, so I think providing simply a
__raw_invocation_type(Fn, Arg1, Arg2, ...) would work?

(And it's up to you whether you'd prefer these arguments to be expressions
or types...)

Ping. Mashall, Eric: do you have a preference on what compiler support you
want here? The most general option is probably:

  __raw_invocation_type(expression)

where the expression is required to be some kind of call expression, and
the type of __raw_invocation_type is the type of the callee. This allows
you to introspect the result of overload resolution, etc.

However, this violates the tradition of std_trait<Args...> mapping exactly
to __std_trait(Args...), so perhaps we should give it a different name to
avoid colliding with other compilers' eventual extensions. Or we could just
provide a __raw_invocation_type trait that takes a single function type and
computes the result type as specified by the TS.

Thoughts?

Looking at N4335 now, I'm a little concerned that we may be standardizing a

Hi Richard,

I've sketched out some of my main concerns.

1. I think compatibility between gcc and clang would be really
helpful. Won't clang have to support GCC's internals in order to
support libstdc++?

2. __raw_invocation_type(expression) has usefulness beyond the traits
in the LFTS. It seems like it could be used to compute the invocation
type of non-member function expressions. Is there any concern with
users directly using this intrinsic to leverage that functionality?

3. As a layman __raw_invocation_type(expression) seems harder to
implement than __raw_invocation_type(Args...). Is that a concern?

4. The name should also reflect that the intrinsics provides the LFTS
v1 semantics. If the semantics change in a future standard we can
provide another differently named intrinsic. My concern is that in the
future, after we have shipped std::invocation_type<...> in C++1z,
libc++ will be unable to detect if clangs provides
`__raw_invocation_type(...)` for LFTS v1 or C++1z.

/Eric