1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_UTILITIES_TEMPLATE_IDIOMS_HPP
  26 #define SHARE_VM_UTILITIES_TEMPLATE_IDIOMS_HPP
  27 
  28 template <typename Base, typename Derived>
  29 struct IsBaseOfHost
  30 {
  31   operator Base*() const;
  32   operator Derived*();
  33 };
  34 
  35 // Statically check if two types are related in a class hierarchy
  36 template <typename Base, typename Derived>
  37 struct is_base_of
  38 {
  39   typedef char yes[1];
  40   typedef char no[2];
  41 
  42   template <typename T> 
  43   static yes &check(Derived*, T);
  44   static no &check(Base*, int);
  45 
  46   static const bool value = sizeof(check(IsBaseOfHost<Base,Derived>(), int())) == sizeof(yes);
  47 };
  48 
  49 // Statically check if two types are equal
  50 template <typename T, typename U>
  51 struct is_same 
  52 {
  53     static const bool value = false; 
  54 };
  55 
  56 template <typename T>
  57 struct is_same<T,T>
  58 { 
  59    static const bool value = true; 
  60 };
  61 
  62 template <typename Base, typename Derived>
  63 struct is_kind_of {
  64   static const bool value = is_same<Base, Derived>::value || is_base_of<Base, Derived>::value;
  65 };
  66 
  67 // Enable a template substitution only if a certain condition holds
  68 template <bool, class T> 
  69 struct enable_if 
  70 {};
  71  
  72 template <class T> 
  73 struct enable_if<true, T> 
  74 { 
  75   typedef T type; 
  76 };
  77 
  78 // Like enable_if but infuse a dependency to a type not in the parameters to the template.
  79 // This would normally make SFINAE fail, but with the infused dependency, all is fine.
  80 template <bool value, class D, class T>
  81 struct enable_if_depend: public enable_if<(sizeof(D) == -1 || value), T>
  82 {};
  83 
  84 // Check for a certain typedef in a class
  85 #define GENERATE_SFINAE_TYPEDEF_CHECK(name)                             \
  86 template <typename T>                                                   \
  87 struct has_typedef_##name {                                             \
  88     typedef char yes[1];                                                \
  89     typedef char no[2];                                                 \
  90                                                                         \
  91     template <typename C>                                               \
  92     static yes& test(typename C::name*);                                \
  93                                                                         \
  94     template <typename>                                                 \
  95     static no& test(...);                                               \
  96                                                                         \
  97     static const bool value = sizeof(test<T>(0)) == sizeof(yes);        \
  98 }
  99 
 100 // TODO: Currently generates compiler error when used on forward declarations
 101 // Check for a certain member declaration
 102 #define GENERATE_SFINAE_MEMBER_CHECK(name)                                      \
 103 template<typename T> struct has_member_##name {                                 \
 104     struct Fallback { int name ; };                                             \
 105     struct Derived: T, Fallback { };                                            \
 106                                                                                 \
 107     template<typename C, C> struct Check;                                       \
 108                                                                                 \
 109     template<typename C> static char (&f(Check<int Fallback::*, &C::name>*))[1];\
 110     template<typename C> static char (&f(...))[2];                              \
 111                                                                                 \
 112     static bool const value = sizeof(f<Derived>(0)) == 2;                       \
 113 }
 114 
 115 // Checks for certain overload of a member function
 116 #define GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(function)                         \
 117 template<typename T, typename Signature>                                        \
 118 struct has_member_function_##function {                                         \
 119     typedef char yes[1];                                                        \
 120     typedef char no [2];                                                        \
 121     template <typename U, U> struct Check;                                      \
 122     template <typename C> static yes &check(Check<Signature, &C::function> *);  \
 123     template <typename  > static no  &check(...);                               \
 124     static bool const value = sizeof(check<T>(0)) == sizeof(yes);               \
 125 }
 126 
 127 GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(do_oop_nv);
 128 GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(do_metadata_nv);
 129 GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(do_klass_nv);
 130 GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(do_class_loader_data_nv);
 131 GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(do_oop);
 132 GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(do_metadata);
 133 GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(do_klass);
 134 GENERATE_SFINAE_MEMBER_FUNCTION_CHECK(do_class_loader_data);
 135 
 136 #endif // SHARE_VM_UTILITIES_TEMPLATE_IDIOMS_HPP
 137