RFR (M): 8183927: Hotspot needs C++ type_traits metaprogramming utilities
Per Liden
per.liden at oracle.com
Mon Jul 10 09:52:20 UTC 2017
Hi Erik,
On 2017-07-06 15:08, Erik Österlund wrote:
> Hi,
>
> I'm sure we have all had moments when we wished we could use the C++11
> type_traits header and the nice metaprogramming tools in there, but then
> suddenly remembered that we can not, because we are building libjvm.so
> with C++03 and are still arguing whether we can use namespaces.
> Well.. welcome to the future. I am delighted to announce that now at
> least some of those tools will become available.
>
> A bunch of C++11 compliant metaprogramming tools that can be used
> already in C++03 have been developed.
> They have been developed with the most conservative and portable C++03
> code possible so that even exotic compilers can support it.
> Special thanks go to Kim Barret whom I have had many long conversations
> about many paragraphs of the C++ standard throughout this work. It has
> helped a lot and improved the code.
>
> While this change introduces the traits without using it in the code
> (more than from gtest), it will become used in already prepared patches
> for refactoring Atomic and OrderAccess to use templates rather than hand
> picked types like the JNI-specific jint etc types. That serves as the
> bottom layer of the upcoming GC barrier interface that also requires
> these utilities. Since they are rather large changes, I hope it is okay
> that I separate out the metaprogramming utilities. I argue that they are
> of value in general in hotspot and will make our lives easier.
>
> All metaprogramming tools have been placed in a new
> hotspot/src/share/vm/metaprogramming directory.
> Tests have been written and placed in a new test/native/metaprogramming
> directory.
>
> A bug ID can be found here:
> https://bugs.openjdk.java.net/browse/JDK-8183927
>
> A webrev with code can be found here:
> http://cr.openjdk.java.net/~eosterlund/8183927/webrev.00/
Looks good!
/Per
>
> Here is a list of metaprogramming tools that have been introduced with a
> corresponding short explanation:
>
> ============================
>
> template<typename T, T v>
> struct IntegralConstant
>
> This metafunction takes as parameters a type and a value.
> The type and value can later be queried from the value_type and value
> members respectively.
>
> Here is an example usage:
> typedef IntegralConstant<bool, true> TrueType;
>
> Now TrueType::value_type is the bool type, and TrueType::value is the
> true boolean value.
>
> Many other metafunctions will later inherit from either TrueType or
> FalseType to e.g. denote the metafunction returning true or false based
> on some condition.
>
> The following traits that start with Is* belong to this category. They
> manifest a constant evaluated at compile time that checks some condition
> of types.
>
> ============================
>
> template <typename X, typename Y>
> struct IsSame
>
> This metafunction takes as parameters two types, X and Y, and returns
> true iff they are the same type. Otherwise it returns false.
>
> ============================
>
> template <typename T>
> struct IsConst
>
> This metafunction takes as parameter a type T, and returns true iff T
> has a const qualifier in it.
>
> ============================
>
> template <typename T>
> struct IsVolatile
>
> This metafunction takes as parameter a type T, and returns true iff T
> has a volatile qualifier in it.
>
> ============================
>
> template<typename T>
> struct IsSigned
>
> This metafunction takes as parameter a type T, and checks if it is
> signed. This is equivalent to asking std::numeric_limits<>::is_signed,
> but additionally disregards CV qualifiers.
>
> ============================
>
> template<typename T>
> struct IsIntegral
>
> This metafunction takes as parameter a type T, and returns true if it is
> an integral type. This is similar to asking
> std::numeric_limits<>::is_integer, but additionally disregards CV
> qualifiers. Note that this returns false for enums.
>
> ============================
>
> template<typename T>
> struct IsSignedIntegral
>
> template<typename T>
> struct IsUnsignedIntegral
>
> These two metafunctions are helpers that return true for integral types
> that have corresponding signedness.
>
> ============================
>
> template <typename T>
> struct IsFloatingPoint
>
> This metafunction takes as parameter a type T, and returns true iff T is
> a floating point type (irrespective of CV qualifiers).
>
> ============================
>
> template <typename T>
> class IsPointer
>
> This metafunction takes as parameter a type T, and returns true iff T is
> a pointer type (irrespective of CV qualifiers).
>
> ============================
>
> That is it as far as metafunctions returning booleans go in these
> changes. So now we move on to metafunctions that make use of these
> boolean conditions.
>
> template <bool condition, typename TrueType, typename FalseType>
> struct Conditional
>
> This metafunction constitutes a conditional type, controlled by the
> condition passed in. Its type evaluates to TrueType iff the condition is
> true, and otherwise evaluates to FalseType.
>
> Here is a contrived toy example:
>
> template<T>
> void example(T base) {
> typedef Conditional<IsPointer<T>::value, ptrdiff_t, T> ScaleType;
> ScaleType offset = offset();
> do_something_clever(base + offset);
> }
>
> ============================
>
> In this example, the type of the offset is ptrdiff_t iff T is a pointer
> and otherwise it is T. This allows passing in pointers and integers to
> the function, and adding offsets into it.
>
> template <bool B, typename T = void>
> struct EnableIf
>
> This metafunction is the key to SFINAE (Substitution Failure Is Not An
> Error), a C++ metaprogramming idiom that allows explicitly allowing or
> disallowing function overloads based on precise conditions for types
> passed in as parameter.
> The EnableIf overload guard should replace the return value of a
> function. The type T is the type that is intended to be returned if the
> overload is allowed based on the passed in condition. By default that is
> void.
>
> Here is a contrived toy example usage:
>
> template <typename T>
> EnableIf<IsIntegral<T>::value> print(T x) {}
>
> template <typename T>
> EnableIf<!IsIntegral<T>::value> print(T x) {}
>
> ...
>
> print(1); // calls the first overload enabled for integral types
> print("hello SFINAE world"); // call the second overload enabled for
> non-integral types
>
> ============================
>
> Now we move on to metafunctions that remove properties like e.g. CV
> qualifiers, pointers and references from types, resulting in a new type.
>
> template <typename T>
> struct RemovePointer
>
> This metafunction takes as parameter a type T, and returns the type
> under the pointer iff T is a pointer, and otherwise returns the same
> type T.
>
> ============================
>
> template <typename T>
> struct RemoveReference
>
> This metafunction takes as parameter a type T, and returns the type
> under the reference iff T is a pointer, and otherwise returns the same
> type T.
>
> ============================
>
> template <typename T>
> struct RemoveCV
>
> This metafunction takes as parameter a type T, and returns the type T
> without CV qualifiers.
>
> ============================
>
> template <typename T>
> struct Decay
>
> This metafunction takes as parameter a type T, and returns the CV
> unqualified type under the reference iff T is a reference type, and
> otherwise returns the CV unqualified type T.
>
> ============================
>
> Testing: A bunch of tests have been added to the
> test/native/metaprogramming folder for all traits (except
> IntegralConstant, because there is not a whole lot to test there, and it
> is used by all condition metafunctions in their corresponding tests).
> They have gone through JPRT, and work well on all oracle supported
> platforms, and is also known to have recently built with the xlC
> compiler on AIX. I would like to ask external maintainers though to
> please verify that this works on your compilers. I have done my best to
> use the most conservative tricks in the book to make it as portable as
> possible, and I hope it will work well for us all.
>
> Thanks,
> /Erik
More information about the hotspot-dev
mailing list