RFR (M): 8183927: Hotspot needs C++ type_traits metaprogramming utilities

Erik Österlund erik.osterlund at oracle.com
Mon Jul 10 10:16:51 UTC 2017


Hi Per,

Thanks for the review!

/Erik

On 2017-07-10 11:52, Per Liden wrote:
> 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