Modernize libartbase/ usage of <type_traits>...

... and other standard library templates.

Use `std::*_t<...>` and `std::*_v<...>` instead of
`std::*<...>::type` and `std::*<...>::value`.

Remove some unnecessary "typename" qualifiers and second
arguments to `static_assert()`.

Test: Rely on TreeHugger.
Change-Id: I4dc8e6fd905c60f652d3ac74bdf3d275b98daee8
diff --git a/libartbase/base/array_ref.h b/libartbase/base/array_ref.h
index 064e26b..859c2a1 100644
--- a/libartbase/base/array_ref.h
+++ b/libartbase/base/array_ref.h
@@ -65,7 +65,7 @@
 
   template <typename U,
             size_t size,
-            typename = typename std::enable_if<std::is_same<T, const U>::value>::type>
+            typename = std::enable_if_t<std::is_same_v<T, const U>>>
   explicit constexpr ArrayRef(U (&array)[size])
       : array_(array), size_(size) {
   }
@@ -75,17 +75,14 @@
   }
 
   template <typename Vector,
-            typename = typename std::enable_if<
-                std::is_same<typename Vector::value_type, value_type>::value>::type>
+            typename = std::enable_if_t<std::is_same_v<typename Vector::value_type, value_type>>>
   explicit ArrayRef(Vector& v)
       : array_(v.data()), size_(v.size()) {
   }
 
   template <typename Vector,
-            typename = typename std::enable_if<
-                std::is_same<
-                    typename std::add_const<typename Vector::value_type>::type,
-                    value_type>::value>::type>
+            typename = std::enable_if_t<
+                std::is_same_v<std::add_const_t<typename Vector::value_type>, value_type>>>
   explicit ArrayRef(const Vector& v)
       : array_(v.data()), size_(v.size()) {
   }
@@ -101,7 +98,7 @@
   }
 
   template <typename U>
-  typename std::enable_if<std::is_same<T, const U>::value, ArrayRef>::type&
+  std::enable_if_t<std::is_same_v<T, const U>, ArrayRef>&
   operator=(const ArrayRef<U>& other) {
     return *this = ArrayRef(other);
   }
diff --git a/libartbase/base/bit_memory_region.h b/libartbase/base/bit_memory_region.h
index cca4217..c5224a5 100644
--- a/libartbase/base/bit_memory_region.h
+++ b/libartbase/base/bit_memory_region.h
@@ -101,8 +101,8 @@
   ATTRIBUTE_NO_SANITIZE_ADDRESS  // We might touch extra bytes due to the alignment.
   ATTRIBUTE_NO_SANITIZE_HWADDRESS  // The hwasan uses different attribute.
   ALWAYS_INLINE Result LoadBits(size_t bit_offset, size_t bit_length) const {
-    static_assert(std::is_integral<Result>::value, "Result must be integral");
-    static_assert(std::is_unsigned<Result>::value, "Result must be unsigned");
+    static_assert(std::is_integral_v<Result>, "Result must be integral");
+    static_assert(std::is_unsigned_v<Result>, "Result must be unsigned");
     DCHECK(IsAligned<sizeof(Result)>(data_));
     DCHECK_LE(bit_offset, bit_size_);
     DCHECK_LE(bit_length, bit_size_ - bit_offset);
diff --git a/libartbase/base/bit_string.h b/libartbase/base/bit_string.h
index d995f8d..cce6fe0 100644
--- a/libartbase/base/bit_string.h
+++ b/libartbase/base/bit_string.h
@@ -38,7 +38,7 @@
  */
 struct BitStringChar {
   using StorageType = uint32_t;
-  static_assert(std::is_unsigned<StorageType>::value, "BitStringChar::StorageType must be unsigned");
+  static_assert(std::is_unsigned_v<StorageType>, "BitStringChar::StorageType must be unsigned");
 
   // BitStringChars are always zero-initialized by default. Equivalent to BitStringChar(0,0).
   BitStringChar() : data_(0u), bitlength_(0u) { }
diff --git a/libartbase/base/bit_struct.h b/libartbase/base/bit_struct.h
index 4cc222c..599e12a 100644
--- a/libartbase/base/bit_struct.h
+++ b/libartbase/base/bit_struct.h
@@ -112,7 +112,7 @@
           size_t kBitWidth,
           typename StorageType>
 struct BitStructField {
-  static_assert(std::is_standard_layout<T>::value, "T must be standard layout");
+  static_assert(std::is_standard_layout_v<T>, "T must be standard layout");
 
   operator T() const {
     return Get();
@@ -120,7 +120,7 @@
 
   // Exclude overload when T==StorageType.
   template <typename _ = void,
-            typename = std::enable_if_t<std::is_same<T, StorageType>::value, _>>
+            typename = std::enable_if_t<std::is_same_v<T, StorageType>, _>>
   explicit operator StorageType() const {
     return BitFieldExtract(storage_, kBitOffset, kBitWidth);
   }
@@ -151,7 +151,7 @@
     // Since C++ doesn't allow the type of operator= to change out
     // in the subclass, reimplement operator= in each subclass
     // manually and call this helper function.
-    static_assert(std::is_base_of<BitStructField, T2>::value, "T2 must inherit BitStructField");
+    static_assert(std::is_base_of_v<BitStructField, T2>, "T2 must inherit BitStructField");
     what.Set(value);
     return what;
   }
@@ -172,10 +172,9 @@
  private:
   using ValueConverter = detail::ValueConverter<T>;
   using ConversionType = typename ValueConverter::StorageType;
-  using ExtractionType =
-      typename std::conditional<std::is_signed_v<ConversionType>,
-                                std::make_signed_t<StorageType>,
-                                StorageType>::type;
+  using ExtractionType = std::conditional_t<std::is_signed_v<ConversionType>,
+                                            std::make_signed_t<StorageType>,
+                                            StorageType>;
 
   StorageType storage_;
 };
diff --git a/libartbase/base/bit_struct_detail.h b/libartbase/base/bit_struct_detail.h
index ad7c0f4..0b891ba 100644
--- a/libartbase/base/bit_struct_detail.h
+++ b/libartbase/base/bit_struct_detail.h
@@ -35,13 +35,12 @@
 template <size_t kBitSize>
 struct MinimumTypeUnsignedHelper {
   using type =
-    typename std::conditional<kBitSize == 0, void,       // NOLINT [whitespace/operators] [3]
-    typename std::conditional<kBitSize <= 8, uint8_t,    // NOLINT [whitespace/operators] [3]
-    typename std::conditional<kBitSize <= 16, uint16_t,  // NOLINT [whitespace/operators] [3]
-    typename std::conditional<kBitSize <= 32, uint32_t,
-    typename std::conditional<kBitSize <= 64, uint64_t,
-    typename std::conditional<kBitSize <= BitSizeOf<uintmax_t>(), uintmax_t,
-                              void>::type>::type>::type>::type>::type>::type;
+    std::conditional_t<kBitSize == 0, void,       // NOLINT [whitespace/operators] [3]
+    std::conditional_t<kBitSize <= 8, uint8_t,    // NOLINT [whitespace/operators] [3]
+    std::conditional_t<kBitSize <= 16, uint16_t,  // NOLINT [whitespace/operators] [3]
+    std::conditional_t<kBitSize <= 32, uint32_t,
+    std::conditional_t<kBitSize <= 64, uint64_t,
+    std::conditional_t<kBitSize <= BitSizeOf<uintmax_t>(), uintmax_t, void>>>>>>;
 };
 
 // Select the smallest [u]intX_t that will fit kBitSize bits.
@@ -51,9 +50,9 @@
   using type_unsigned = typename MinimumTypeUnsignedHelper<kBitSize>::type;
 
   using type =
-    typename std::conditional</* if */   std::is_signed<T>::value,
-                              /* then */ typename std::make_signed<type_unsigned>::type,
-                              /* else */ type_unsigned>::type;
+    std::conditional_t</* if */   std::is_signed_v<T>,
+                       /* then */ std::make_signed_t<type_unsigned>,
+                       /* else */ type_unsigned>;
 };
 
 // Helper for converting to and from T to an integral type.
@@ -119,8 +118,8 @@
 template <typename T>
 struct HasUnderscoreField {
  private:
-  using TrueT = std::integral_constant<bool, true>::type;
-  using FalseT = std::integral_constant<bool, false>::type;
+  using TrueT = std::bool_constant<true>::type;
+  using FalseT = std::bool_constant<false>::type;
 
   template <typename C>
   static constexpr auto Test(void*) -> decltype(std::declval<C>()._, TrueT{});
@@ -140,13 +139,13 @@
 // Nominally used by the BITSTRUCT_DEFINE_END macro.
 template <typename T>
 static constexpr bool ValidateBitStructSize() {
-  static_assert(std::is_union<T>::value, "T must be union");
-  static_assert(std::is_standard_layout<T>::value, "T must be standard-layout");
+  static_assert(std::is_union_v<T>, "T must be union");
+  static_assert(std::is_standard_layout_v<T>, "T must be standard-layout");
   static_assert(HasUnderscoreField<T>::value, "T must have the _ DefineBitStructSize");
 
   const size_t kBitStructSizeOf = BitStructSizeOf<T>();
-  static_assert(std::is_same<decltype(GetMemberType(&T::_)),
-                             DefineBitStructSize<kBitStructSizeOf>>::value,
+  static_assert(std::is_same_v<decltype(GetMemberType(&T::_)),
+                               DefineBitStructSize<kBitStructSizeOf>>,
                 "T::_ must be a DefineBitStructSize of the same size");
 
   const size_t kExpectedSize = (BitStructSizeOf<T>() < kBitsPerByte)
diff --git a/libartbase/base/bit_utils.h b/libartbase/base/bit_utils.h
index 58cc78c..ffaffc3 100644
--- a/libartbase/base/bit_utils.h
+++ b/libartbase/base/bit_utils.h
@@ -30,8 +30,8 @@
 // Like sizeof, but count how many bits a type takes. Pass type explicitly.
 template <typename T>
 constexpr size_t BitSizeOf() {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  using unsigned_type = typename std::make_unsigned<T>::type;
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  using unsigned_type = std::make_unsigned_t<T>;
   static_assert(sizeof(T) == sizeof(unsigned_type), "Unexpected type size mismatch!");
   static_assert(std::numeric_limits<unsigned_type>::radix == 2, "Unexpected radix!");
   return std::numeric_limits<unsigned_type>::digits;
@@ -45,8 +45,8 @@
 
 template<typename T>
 constexpr int CLZ(T x) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  static_assert(std::is_unsigned_v<T>, "T must be unsigned");
   static_assert(std::numeric_limits<T>::radix == 2, "Unexpected radix!");
   static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t),
                 "Unsupported sizeof(T)");
@@ -60,14 +60,14 @@
 // Similar to CLZ except that on zero input it returns bitwidth and supports signed integers.
 template<typename T>
 constexpr int JAVASTYLE_CLZ(T x) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  using unsigned_type = typename std::make_unsigned<T>::type;
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  using unsigned_type = std::make_unsigned_t<T>;
   return (x == 0) ? BitSizeOf<T>() : CLZ(static_cast<unsigned_type>(x));
 }
 
 template<typename T>
 constexpr int CTZ(T x) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
+  static_assert(std::is_integral_v<T>, "T must be integral");
   // It is not unreasonable to ask for trailing zeros in a negative number. As such, do not check
   // that T is an unsigned type.
   static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t),
@@ -79,8 +79,8 @@
 // Similar to CTZ except that on zero input it returns bitwidth and supports signed integers.
 template<typename T>
 constexpr int JAVASTYLE_CTZ(T x) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  using unsigned_type = typename std::make_unsigned<T>::type;
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  using unsigned_type = std::make_unsigned_t<T>;
   return (x == 0) ? BitSizeOf<T>() : CTZ(static_cast<unsigned_type>(x));
 }
 
@@ -105,8 +105,8 @@
 // Find the bit position of the most significant bit (0-based), or -1 if there were no bits set.
 template <typename T>
 constexpr ssize_t MostSignificantBit(T value) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  static_assert(std::is_unsigned_v<T>, "T must be unsigned");
   static_assert(std::numeric_limits<T>::radix == 2, "Unexpected radix!");
   return (value == 0) ? -1 : std::numeric_limits<T>::digits - 1 - CLZ(value);
 }
@@ -114,8 +114,8 @@
 // Find the bit position of the least significant bit (0-based), or -1 if there were no bits set.
 template <typename T>
 constexpr ssize_t LeastSignificantBit(T value) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  static_assert(std::is_unsigned_v<T>, "T must be unsigned");
   return (value == 0) ? -1 : CTZ(value);
 }
 
@@ -127,8 +127,8 @@
 
 template <typename T>
 constexpr T RoundUpToPowerOfTwo(T x) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  static_assert(std::is_unsigned_v<T>, "T must be unsigned");
   // NOTE: Undefined if x > (1 << (std::numeric_limits<T>::digits - 1)).
   return (x < 2u) ? x : static_cast<T>(1u) << (std::numeric_limits<T>::digits - CLZ(x - 1u));
 }
@@ -136,21 +136,21 @@
 // Return highest possible N - a power of two - such that val >= N.
 template <typename T>
 constexpr T TruncToPowerOfTwo(T val) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  static_assert(std::is_unsigned_v<T>, "T must be unsigned");
   return (val != 0) ? static_cast<T>(1u) << (BitSizeOf<T>() - CLZ(val) - 1u) : 0;
 }
 
 template<typename T>
 constexpr bool IsPowerOfTwo(T x) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
+  static_assert(std::is_integral_v<T>, "T must be integral");
   // TODO: assert unsigned. There is currently many uses with signed values.
   return (x & (x - 1)) == 0;
 }
 
 template<typename T>
 constexpr int WhichPowerOf2(T x) {
-  static_assert(std::is_integral<T>::value, "T must be integral");
+  static_assert(std::is_integral_v<T>, "T must be integral");
   // TODO: assert unsigned. There is currently many uses with signed values.
   DCHECK((x != 0) && IsPowerOfTwo(x));
   return CTZ(x);
@@ -168,10 +168,10 @@
 }
 
 template<typename T>
-constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) WARN_UNUSED;
+constexpr T RoundUp(T x, std::remove_reference_t<T> n) WARN_UNUSED;
 
 template<typename T>
-constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
+constexpr T RoundUp(T x, std::remove_reference_t<T> n) {
   return RoundDown(x + n - 1, n);
 }
 
@@ -265,7 +265,7 @@
 constexpr bool IsInt(T value) {
   static_assert(kBits > 0, "kBits cannot be zero.");
   static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
-  static_assert(std::is_signed<T>::value, "Needs a signed type.");
+  static_assert(std::is_signed_v<T>, "Needs a signed type.");
   // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
   // trivially true.
   return (kBits == BitSizeOf<T>()) ?
@@ -277,12 +277,12 @@
 constexpr bool IsUint(T value) {
   static_assert(kBits > 0, "kBits cannot be zero.");
   static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
-  static_assert(std::is_integral<T>::value, "Needs an integral type.");
+  static_assert(std::is_integral_v<T>, "Needs an integral type.");
   // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
   // trivially true.
   // NOTE: To avoid triggering assertion in GetIntLimit(kBits+1) if kBits+1==BitSizeOf<T>(),
   // use GetIntLimit(kBits)*2u. The unsigned arithmetic works well for us if it overflows.
-  using unsigned_type = typename std::make_unsigned<T>::type;
+  using unsigned_type = std::make_unsigned_t<T>;
   return (0 <= value) &&
       (kBits == BitSizeOf<T>() ||
           (static_cast<unsigned_type>(value) <= GetIntLimit<unsigned_type>(kBits) * 2u - 1u));
@@ -291,8 +291,8 @@
 template <size_t kBits, typename T>
 constexpr bool IsAbsoluteUint(T value) {
   static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
-  static_assert(std::is_integral<T>::value, "Needs an integral type.");
-  using unsigned_type = typename std::make_unsigned<T>::type;
+  static_assert(std::is_integral_v<T>, "Needs an integral type.");
+  using unsigned_type = std::make_unsigned_t<T>;
   return (kBits == BitSizeOf<T>())
       ? true
       : IsUint<kBits>(value < 0
@@ -303,23 +303,23 @@
 // Generate maximum/minimum values for signed/unsigned n-bit integers
 template <typename T>
 constexpr T MaxInt(size_t bits) {
-  DCHECK(std::is_unsigned<T>::value || bits > 0u) << "bits cannot be zero for signed.";
+  DCHECK(std::is_unsigned_v<T> || bits > 0u) << "bits cannot be zero for signed.";
   DCHECK_LE(bits, BitSizeOf<T>());
-  using unsigned_type = typename std::make_unsigned<T>::type;
+  using unsigned_type = std::make_unsigned_t<T>;
   return bits == BitSizeOf<T>()
       ? std::numeric_limits<T>::max()
-      : std::is_signed<T>::value
+      : std::is_signed_v<T>
           ? ((bits == 1u) ? 0 : static_cast<T>(MaxInt<unsigned_type>(bits - 1)))
           : static_cast<T>(UINT64_C(1) << bits) - static_cast<T>(1);
 }
 
 template <typename T>
 constexpr T MinInt(size_t bits) {
-  DCHECK(std::is_unsigned<T>::value || bits > 0) << "bits cannot be zero for signed.";
+  DCHECK(std::is_unsigned_v<T> || bits > 0) << "bits cannot be zero for signed.";
   DCHECK_LE(bits, BitSizeOf<T>());
   return bits == BitSizeOf<T>()
       ? std::numeric_limits<T>::min()
-      : std::is_signed<T>::value
+      : std::is_signed_v<T>
           ? ((bits == 1u) ? -1 : static_cast<T>(-1) - MaxInt<T>(bits))
           : static_cast<T>(0);
 }
@@ -334,7 +334,7 @@
 // Returns value with bit set in hightest one-bit position or 0 if 0.  (java.lang.X.highestOneBit).
 template <typename T>
 inline static T HighestOneBitValue(T opnd) {
-  using unsigned_type = typename std::make_unsigned<T>::type;
+  using unsigned_type = std::make_unsigned_t<T>;
   T res;
   if (opnd == 0) {
     res = 0;
@@ -351,7 +351,7 @@
   int mask = BitSizeOf<T>() - 1;
   int unsigned_right_shift = left ? (-distance & mask) : (distance & mask);
   int signed_left_shift = left ? (distance & mask) : (-distance & mask);
-  using unsigned_type = typename std::make_unsigned<T>::type;
+  using unsigned_type = std::make_unsigned_t<T>;
   return (static_cast<unsigned_type>(opnd) >> unsigned_right_shift) | (opnd << signed_left_shift);
 }
 
@@ -485,7 +485,7 @@
 
   const T bitfield_unsigned =
       static_cast<T>((val >> lsb) & MaskLeastSignificant<T>(width));
-  if (std::is_signed<T>::value) {
+  if (std::is_signed_v<T>) {
     // Perform sign extension
     if (width == 0) {  // Avoid underflow.
       return static_cast<T>(0);
diff --git a/libartbase/base/bit_utils_iterator.h b/libartbase/base/bit_utils_iterator.h
index 4975ebf..bfcff86 100644
--- a/libartbase/base/bit_utils_iterator.h
+++ b/libartbase/base/bit_utils_iterator.h
@@ -34,8 +34,8 @@
 template <typename T, typename Iter>
 class BitIteratorBase
     : public std::iterator<std::forward_iterator_tag, uint32_t, ptrdiff_t, void, void> {
-  static_assert(std::is_integral<T>::value, "T must be integral");
-  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(std::is_integral_v<T>, "T must be integral");
+  static_assert(std::is_unsigned_v<T>, "T must be unsigned");
 
   static_assert(sizeof(T) == sizeof(uint32_t) || sizeof(T) == sizeof(uint64_t), "Unsupported size");
 
diff --git a/libartbase/base/casts.h b/libartbase/base/casts.h
index cedd624..c88f589 100644
--- a/libartbase/base/casts.h
+++ b/libartbase/base/casts.h
@@ -71,7 +71,7 @@
 
 template<typename To, typename From>     // use like this: down_cast<T*>(foo);
 inline To down_cast(From* f) {                   // so we only accept pointers
-  static_assert(std::is_base_of<From, typename std::remove_pointer<To>::type>::value,
+  static_assert(std::is_base_of_v<From, std::remove_pointer_t<To>>,
                 "down_cast unsafe as To is not a subtype of From");
 
   return static_cast<To>(f);
@@ -79,7 +79,7 @@
 
 template<typename To, typename From>     // use like this: down_cast<T&>(foo);
 inline To down_cast(From& f) {           // so we only accept references
-  static_assert(std::is_base_of<From, typename std::remove_reference<To>::type>::value,
+  static_assert(std::is_base_of_v<From, std::remove_reference_t<To>>,
                 "down_cast unsafe as To is not a subtype of From");
 
   return static_cast<To>(f);
@@ -121,24 +121,22 @@
 
 template <typename Dest, typename Source>
 constexpr
-typename std::enable_if<!std::is_enum<Source>::value, Dest>::type
-enum_cast(Source value) {
-  return static_cast<Dest>(
-      dchecked_integral_cast<typename std::underlying_type<Dest>::type>(value));
+std::enable_if_t<!std::is_enum_v<Source>, Dest> enum_cast(Source value) {
+  return static_cast<Dest>(dchecked_integral_cast<std::underlying_type_t<Dest>>(value));
 }
 
 template <typename Dest = void, typename Source>
 constexpr
-typename std::enable_if<std::is_enum<Source>::value,
-                        typename std::conditional<std::is_same<Dest, void>::value,
-                                                  std::underlying_type<Source>,
-                                                  Identity<Dest>>::type>::type::type
+typename std::enable_if_t<std::is_enum_v<Source>,
+                          std::conditional_t<std::is_same_v<Dest, void>,
+                                             std::underlying_type<Source>,
+                                             Identity<Dest>>>::type
 enum_cast(Source value) {
-  using return_type = typename std::conditional<std::is_same<Dest, void>::value,
-                                                std::underlying_type<Source>,
-                                                Identity<Dest>>::type::type;
+  using return_type = typename std::conditional_t<std::is_same_v<Dest, void>,
+                                                  std::underlying_type<Source>,
+                                                  Identity<Dest>>::type;
   return dchecked_integral_cast<return_type>(
-      static_cast<typename std::underlying_type<Source>::type>(value));
+      static_cast<std::underlying_type_t<Source>>(value));
 }
 
 // A version of reinterpret_cast<>() between pointers and int64_t/uint64_t
@@ -147,9 +145,9 @@
 template <typename Dest, typename Source>
 inline Dest reinterpret_cast64(Source source) {
   // This is the overload for casting from int64_t/uint64_t to a pointer.
-  static_assert(std::is_same<Source, int64_t>::value || std::is_same<Source, uint64_t>::value,
+  static_assert(std::is_same_v<Source, int64_t> || std::is_same_v<Source, uint64_t>,
                 "Source must be int64_t or uint64_t.");
-  static_assert(std::is_pointer<Dest>::value, "Dest must be a pointer.");
+  static_assert(std::is_pointer_v<Dest>, "Dest must be a pointer.");
   // Check that we don't lose any non-0 bits here.
   DCHECK_EQ(static_cast<Source>(static_cast<uintptr_t>(source)), source);
   return reinterpret_cast<Dest>(static_cast<uintptr_t>(source));
@@ -158,7 +156,7 @@
 template <typename Dest, typename Source>
 inline Dest reinterpret_cast64(Source* ptr) {
   // This is the overload for casting from a pointer to int64_t/uint64_t.
-  static_assert(std::is_same<Dest, int64_t>::value || std::is_same<Dest, uint64_t>::value,
+  static_assert(std::is_same_v<Dest, int64_t> || std::is_same_v<Dest, uint64_t>,
                 "Dest must be int64_t or uint64_t.");
   static_assert(sizeof(uintptr_t) <= sizeof(Dest), "Expecting at most 64-bit pointers.");
   return static_cast<Dest>(reinterpret_cast<uintptr_t>(ptr));
@@ -170,9 +168,9 @@
 template <typename Dest, typename Source>
 inline Dest reinterpret_cast32(Source source) {
   // This is the overload for casting from int32_t/uint32_t to a pointer.
-  static_assert(std::is_same<Source, int32_t>::value || std::is_same<Source, uint32_t>::value,
+  static_assert(std::is_same_v<Source, int32_t> || std::is_same_v<Source, uint32_t>,
                 "Source must be int32_t or uint32_t.");
-  static_assert(std::is_pointer<Dest>::value, "Dest must be a pointer.");
+  static_assert(std::is_pointer_v<Dest>, "Dest must be a pointer.");
   // Check that we don't lose any non-0 bits here.
   static_assert(sizeof(uintptr_t) >= sizeof(Source), "Expecting at least 32-bit pointers.");
   return reinterpret_cast<Dest>(static_cast<uintptr_t>(static_cast<uint32_t>(source)));
@@ -181,7 +179,7 @@
 template <typename Dest, typename Source>
 inline Dest reinterpret_cast32(Source* ptr) {
   // This is the overload for casting from a pointer to int32_t/uint32_t.
-  static_assert(std::is_same<Dest, int32_t>::value || std::is_same<Dest, uint32_t>::value,
+  static_assert(std::is_same_v<Dest, int32_t> || std::is_same_v<Dest, uint32_t>,
                 "Dest must be int32_t or uint32_t.");
   static_assert(sizeof(uintptr_t) >= sizeof(Dest), "Expecting at least 32-bit pointers.");
   return static_cast<Dest>(dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr)));
diff --git a/libartbase/base/dchecked_vector.h b/libartbase/base/dchecked_vector.h
index 66e9638..ecb4d2a 100644
--- a/libartbase/base/dchecked_vector.h
+++ b/libartbase/base/dchecked_vector.h
@@ -37,7 +37,7 @@
 class dchecked_vector : private std::vector<T, Alloc> {
  private:
   // std::vector<> has a slightly different specialization for bool. We don't provide that.
-  static_assert(!std::is_same<T, bool>::value, "Not implemented for bool.");
+  static_assert(!std::is_same_v<T, bool>, "Not implemented for bool.");
   using Base = std::vector<T, Alloc>;
 
  public:
diff --git a/libartbase/base/hash_set.h b/libartbase/base/hash_set.h
index 7ed8c61..c4af1b6 100644
--- a/libartbase/base/hash_set.h
+++ b/libartbase/base/hash_set.h
@@ -50,9 +50,9 @@
   // Conversion from iterator to const_iterator.
   template <class OtherElem,
             class OtherHashSetType,
-            typename = typename std::enable_if<
-                std::is_same<Elem, const OtherElem>::value &&
-                std::is_same<HashSetType, const OtherHashSetType>::value>::type>
+            typename = std::enable_if_t<
+                std::is_same_v<Elem, const OtherElem> &&
+                std::is_same_v<HashSetType, const OtherHashSetType>>>
   HashSetIterator(const HashSetIterator<OtherElem, OtherHashSetType>& other)
       : index_(other.index_), hash_set_(other.hash_set_) {}
 
@@ -102,10 +102,10 @@
 bool operator==(const HashSetIterator<Elem1, HashSetType1>& lhs,
                 const HashSetIterator<Elem2, HashSetType2>& rhs) {
   static_assert(
-      std::is_convertible<HashSetIterator<Elem1, HashSetType1>,
-                          HashSetIterator<Elem2, HashSetType2>>::value ||
-      std::is_convertible<HashSetIterator<Elem2, HashSetType2>,
-                          HashSetIterator<Elem1, HashSetType1>>::value, "Bad iterator types.");
+      std::is_convertible_v<HashSetIterator<Elem1, HashSetType1>,
+                            HashSetIterator<Elem2, HashSetType2>> ||
+      std::is_convertible_v<HashSetIterator<Elem2, HashSetType2>,
+                            HashSetIterator<Elem1, HashSetType1>>, "Bad iterator types.");
   DCHECK_EQ(lhs.hash_set_, rhs.hash_set_);
   return lhs.index_ == rhs.index_;
 }
@@ -140,9 +140,7 @@
 };
 
 template <class T>
-using DefaultHashFn = typename std::conditional<std::is_same<T, std::string>::value,
-                                                DataHash,
-                                                std::hash<T>>::type;
+using DefaultHashFn = std::conditional_t<std::is_same_v<T, std::string>, DataHash, std::hash<T>>;
 
 struct DefaultStringEquals {
   // Allow comparison with anything that can be compared to std::string,
@@ -154,9 +152,8 @@
 };
 
 template <class T>
-using DefaultPred = typename std::conditional<std::is_same<T, std::string>::value,
-                                              DefaultStringEquals,
-                                              std::equal_to<T>>::type;
+using DefaultPred =
+    std::conditional_t<std::is_same_v<T, std::string>, DefaultStringEquals, std::equal_to<T>>;
 
 // Low memory version of a hash set, uses less memory than std::unordered_multiset since elements
 // aren't boxed. Uses linear probing to resolve collisions.
@@ -509,7 +506,7 @@
     return InsertWithHash(std::move(element), hashfn_(element));
   }
 
-  template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
+  template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
   std::pair<iterator, bool> InsertWithHash(U&& element, size_t hash) {
     DCHECK_EQ(hash, hashfn_(element));
     if (num_elements_ >= elements_until_expand_) {
@@ -537,7 +534,7 @@
     return PutWithHash(std::move(element), hashfn_(element));
   }
 
-  template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
+  template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
   void PutWithHash(U&& element, size_t hash) {
     DCHECK_EQ(hash, hashfn_(element));
     if (num_elements_ >= elements_until_expand_) {
diff --git a/libartbase/base/intrusive_forward_list.h b/libartbase/base/intrusive_forward_list.h
index 29db64d..2e66f3e 100644
--- a/libartbase/base/intrusive_forward_list.h
+++ b/libartbase/base/intrusive_forward_list.h
@@ -55,8 +55,7 @@
 class IntrusiveForwardListBaseHookTraits;
 
 template <typename T,
-          typename HookTraits =
-              IntrusiveForwardListBaseHookTraits<typename std::remove_const<T>::type>>
+          typename HookTraits = IntrusiveForwardListBaseHookTraits<std::remove_const_t<T>>>
 class IntrusiveForwardList;
 
 template <typename T, typename HookTraits>
@@ -69,7 +68,7 @@
 
   // Conversion from iterator to const_iterator.
   template <typename OtherT,
-            typename = typename std::enable_if<std::is_same<T, const OtherT>::value>::type>
+            typename = std::enable_if_t<std::is_same_v<T, const OtherT>>>
   IntrusiveForwardListIterator(const IntrusiveForwardListIterator<OtherT, HookTraits>& src)  // NOLINT, implicit
       : hook_(src.hook_) { }
 
@@ -106,20 +105,20 @@
   friend class IntrusiveForwardList;
 
   template <typename OtherT1, typename OtherT2, typename OtherTraits>
-  friend typename std::enable_if<std::is_same<const OtherT1, const OtherT2>::value, bool>::type
+  friend std::enable_if_t<std::is_same_v<const OtherT1, const OtherT2>, bool>
   operator==(const IntrusiveForwardListIterator<OtherT1, OtherTraits>& lhs,
              const IntrusiveForwardListIterator<OtherT2, OtherTraits>& rhs);
 };
 
 template <typename T, typename OtherT, typename HookTraits>
-typename std::enable_if<std::is_same<const T, const OtherT>::value, bool>::type operator==(
+std::enable_if_t<std::is_same_v<const T, const OtherT>, bool> operator==(
     const IntrusiveForwardListIterator<T, HookTraits>& lhs,
     const IntrusiveForwardListIterator<OtherT, HookTraits>& rhs) {
   return lhs.hook_ == rhs.hook_;
 }
 
 template <typename T, typename OtherT, typename HookTraits>
-typename std::enable_if<std::is_same<const T, const OtherT>::value, bool>::type operator!=(
+std::enable_if_t<std::is_same_v<const T, const OtherT>, bool> operator!=(
     const IntrusiveForwardListIterator<T, HookTraits>& lhs,
     const IntrusiveForwardListIterator<OtherT, HookTraits>& rhs) {
   return !(lhs == rhs);
diff --git a/libartbase/base/intrusive_forward_list_test.cc b/libartbase/base/intrusive_forward_list_test.cc
index e97c304..595210b 100644
--- a/libartbase/base/intrusive_forward_list_test.cc
+++ b/libartbase/base/intrusive_forward_list_test.cc
@@ -731,7 +731,7 @@
   ModifyValue<IFLTestValueList>();
   // Does not compile with ConstIFLTestValueList because LHS of the assignment is const.
   // ModifyValue<ConstIFLTestValueList>();
-  static_assert(std::is_const<ConstIFLTestValueList::iterator::value_type>::value, "Const check.");
+  static_assert(std::is_const_v<ConstIFLTestValueList::iterator::value_type>);
   ModifyValue<IFLTestValue2List>();
 }
 
diff --git a/libartbase/base/leb128.h b/libartbase/base/leb128.h
index b866d37..4f0f975 100644
--- a/libartbase/base/leb128.h
+++ b/libartbase/base/leb128.h
@@ -216,7 +216,7 @@
 // (2) there is another Leb128 value before this one.
 template <typename T>
 static inline T* ReverseSearchUnsignedLeb128(T* end_ptr) {
-  static_assert(std::is_same<typename std::remove_const<T>::type, uint8_t>::value,
+  static_assert(std::is_same_v<std::remove_const_t<T>, uint8_t>,
                 "T must be a uint8_t");
   T* ptr = end_ptr;
 
@@ -257,7 +257,7 @@
 
 template <typename Vector>
 static inline void EncodeUnsignedLeb128(Vector* dest, uint32_t value) {
-  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+  static_assert(std::is_same_v<typename Vector::value_type, uint8_t>, "Invalid value type");
   uint8_t out = value & 0x7f;
   value >>= 7;
   while (value != 0) {
@@ -296,7 +296,7 @@
 
 template<typename Vector>
 static inline void EncodeSignedLeb128(Vector* dest, int32_t value) {
-  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+  static_assert(std::is_same_v<typename Vector::value_type, uint8_t>, "Invalid value type");
   uint32_t extra_bits = static_cast<uint32_t>(value ^ (value >> 31)) >> 6;
   uint8_t out = value & 0x7f;
   while (extra_bits != 0u) {
@@ -311,7 +311,7 @@
 // An encoder that pushes int32_t/uint32_t data onto the given std::vector.
 template <typename Vector = std::vector<uint8_t>>
 class Leb128Encoder {
-  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+  static_assert(std::is_same_v<typename Vector::value_type, uint8_t>, "Invalid value type");
 
  public:
   explicit Leb128Encoder(Vector* data) : data_(data) {
@@ -359,7 +359,7 @@
 template <typename Vector = std::vector<uint8_t>>
 class Leb128EncodingVector final : private Vector,
                                    public Leb128Encoder<Vector> {
-  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+  static_assert(std::is_same_v<typename Vector::value_type, uint8_t>, "Invalid value type");
 
  public:
   Leb128EncodingVector() : Leb128Encoder<Vector>(this) { }
diff --git a/libartbase/base/safe_map.h b/libartbase/base/safe_map.h
index 0d7a8c1..7ae85d4 100644
--- a/libartbase/base/safe_map.h
+++ b/libartbase/base/safe_map.h
@@ -149,7 +149,7 @@
 
   template <typename CreateFn>
   V& GetOrCreate(const K& k, CreateFn create) {
-    static_assert(std::is_same<V, typename std::result_of<CreateFn()>::type>::value,
+    static_assert(std::is_same_v<V, std::result_of_t<CreateFn()>>,
                   "Argument `create` should return a value of type V.");
     auto lb = lower_bound(k);
     if (lb != end() && !key_comp()(k, lb->first)) {
diff --git a/libartbase/base/scoped_arena_containers.h b/libartbase/base/scoped_arena_containers.h
index 882fdcc..5f0cfe6 100644
--- a/libartbase/base/scoped_arena_containers.h
+++ b/libartbase/base/scoped_arena_containers.h
@@ -274,7 +274,7 @@
 class ArenaDelete<T[]> {
  public:
   void operator()(T* ptr ATTRIBUTE_UNUSED) const {
-    static_assert(std::is_trivially_destructible<T>::value,
+    static_assert(std::is_trivially_destructible_v<T>,
                   "ArenaUniquePtr does not support non-trivially-destructible arrays.");
     // TODO: Implement debug checks, and MEMORY_TOOL support.
   }
diff --git a/libartbase/base/stl_util.h b/libartbase/base/stl_util.h
index dfe994e..0ae4fd2 100644
--- a/libartbase/base/stl_util.h
+++ b/libartbase/base/stl_util.h
@@ -290,7 +290,7 @@
 template <typename Val>
 struct NonNullFilter {
  public:
-  static_assert(std::is_pointer<Val>::value, "Must be pointer type!");
+  static_assert(std::is_pointer_v<Val>, "Must be pointer type!");
   constexpr bool operator()(Val v) const {
     return v != nullptr;
   }
diff --git a/libartbase/base/transform_array_ref.h b/libartbase/base/transform_array_ref.h
index 2f56e9b..9413b22 100644
--- a/libartbase/base/transform_array_ref.h
+++ b/libartbase/base/transform_array_ref.h
@@ -36,7 +36,7 @@
   using FallbackConstIter = std::iterator<std::random_access_iterator_tag, void, void, void, void>;
   using PreferredConstIter =
       TransformIterator<typename ArrayRef<BaseType>::const_iterator, Function>;
-  template <typename F, typename = typename std::result_of<F(const BaseType&)>::type>
+  template <typename F, typename = std::result_of_t<F(const BaseType&)>>
   static PreferredConstIter ConstIterHelper(int&);
   template <typename F>
   static FallbackConstIter ConstIterHelper(const int&);
@@ -50,15 +50,12 @@
   using pointer = typename Iter::pointer;
   using const_pointer = typename ConstIter::pointer;
   using iterator = Iter;
-  using const_iterator = typename std::conditional<
-      std::is_same<ConstIter, FallbackConstIter>::value,
-      void,
-      ConstIter>::type;
+  using const_iterator =
+      std::conditional_t<std::is_same_v<ConstIter, FallbackConstIter>, void, ConstIter>;
   using reverse_iterator = std::reverse_iterator<Iter>;
-  using const_reverse_iterator = typename std::conditional<
-      std::is_same<ConstIter, FallbackConstIter>::value,
-      void,
-      std::reverse_iterator<ConstIter>>::type;
+  using const_reverse_iterator = std::conditional_t<std::is_same_v<ConstIter, FallbackConstIter>,
+                                                    void,
+                                                    std::reverse_iterator<ConstIter>>;
   using difference_type = typename ArrayRef<BaseType>::difference_type;
   using size_type = typename ArrayRef<BaseType>::size_type;
 
@@ -71,7 +68,7 @@
       : data_(base, fn) { }
 
   template <typename OtherBT,
-            typename = typename std::enable_if<std::is_same<BaseType, const OtherBT>::value>::type>
+            typename = std::enable_if_t<std::is_same_v<BaseType, const OtherBT>>>
   TransformArrayRef(const TransformArrayRef<OtherBT, Function>& other)
       : TransformArrayRef(other.base(), other.GetFunction()) { }
 
@@ -80,7 +77,7 @@
   TransformArrayRef& operator=(const TransformArrayRef& other) = default;
 
   template <typename OtherBT,
-            typename = typename std::enable_if<std::is_same<BaseType, const OtherBT>::value>::type>
+            typename = std::enable_if_t<std::is_same_v<BaseType, const OtherBT>>>
   TransformArrayRef& operator=(const TransformArrayRef<OtherBT, Function>& other) {
     return *this = TransformArrayRef(other.base(), other.GetFunction());
   }
diff --git a/libartbase/base/transform_array_ref_test.cc b/libartbase/base/transform_array_ref_test.cc
index 896209b..4ac6978 100644
--- a/libartbase/base/transform_array_ref_test.cc
+++ b/libartbase/base/transform_array_ref_test.cc
@@ -44,12 +44,11 @@
   auto taref = MakeTransformArrayRef(input, add1);
   using TarefIter = decltype(taref)::iterator;
   using ConstTarefIter = decltype(taref)::const_iterator;
-  static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type");
-  static_assert(std::is_same<TarefIter, decltype(taref)::pointer>::value, "pointer");
-  static_assert(std::is_same<int, decltype(taref)::reference>::value, "reference");
-  static_assert(std::is_same<ConstTarefIter, decltype(taref)::const_pointer>::value,
-                "const_pointer");
-  static_assert(std::is_same<int, decltype(taref)::const_reference>::value, "const_reference");
+  static_assert(std::is_same_v<int, decltype(taref)::value_type>);
+  static_assert(std::is_same_v<TarefIter, decltype(taref)::pointer>);
+  static_assert(std::is_same_v<int, decltype(taref)::reference>);
+  static_assert(std::is_same_v<ConstTarefIter, decltype(taref)::const_pointer>);
+  static_assert(std::is_same_v<int, decltype(taref)::const_reference>);
 
   std::copy(taref.begin(), taref.end(), std::back_inserter(output));
   ASSERT_EQ(std::vector<int>({ 8, 7, 5, 1 }), output);
@@ -84,12 +83,12 @@
 
   auto taref = MakeTransformArrayRef(input, sub1);
   using TarefIter = decltype(taref)::iterator;
-  static_assert(std::is_same<void, decltype(taref)::const_iterator>::value, "const_iterator");
-  static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type");
-  static_assert(std::is_same<TarefIter, decltype(taref)::pointer>::value, "pointer");
-  static_assert(std::is_same<int, decltype(taref)::reference>::value, "reference");
-  static_assert(std::is_same<void, decltype(taref)::const_pointer>::value, "const_pointer");
-  static_assert(std::is_same<void, decltype(taref)::const_reference>::value, "const_reference");
+  static_assert(std::is_same_v<void, decltype(taref)::const_iterator>);
+  static_assert(std::is_same_v<int, decltype(taref)::value_type>);
+  static_assert(std::is_same_v<TarefIter, decltype(taref)::pointer>);
+  static_assert(std::is_same_v<int, decltype(taref)::reference>);
+  static_assert(std::is_same_v<void, decltype(taref)::const_pointer>);
+  static_assert(std::is_same_v<void, decltype(taref)::const_reference>);
 
   std::copy(taref.begin(), taref.end(), std::back_inserter(output));
   ASSERT_EQ(std::vector<int>({ 3, 3, 4, 6, 9 }), output);
@@ -119,12 +118,11 @@
   std::vector<int> output;
 
   auto taref = MakeTransformArrayRef(input, ref);
-  static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type");
-  static_assert(std::is_same<int*, decltype(taref)::pointer>::value, "pointer");
-  static_assert(std::is_same<int&, decltype(taref)::reference>::value, "reference");
-  static_assert(std::is_same<const int*, decltype(taref)::const_pointer>::value, "const_pointer");
-  static_assert(std::is_same<const int&, decltype(taref)::const_reference>::value,
-                "const_reference");
+  static_assert(std::is_same_v<int, decltype(taref)::value_type>);
+  static_assert(std::is_same_v<int*, decltype(taref)::pointer>);
+  static_assert(std::is_same_v<int&, decltype(taref)::reference>);
+  static_assert(std::is_same_v<const int*, decltype(taref)::const_pointer>);
+  static_assert(std::is_same_v<const int&, decltype(taref)::const_reference>);
 
   std::copy(taref.begin(), taref.end(), std::back_inserter(output));
   ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
@@ -163,12 +161,11 @@
   const std::vector<ValueHolder>& cinput = input;
 
   auto ctaref = MakeTransformArrayRef(cinput, ref);
-  static_assert(std::is_same<int, decltype(ctaref)::value_type>::value, "value_type");
-  static_assert(std::is_same<const int*, decltype(ctaref)::pointer>::value, "pointer");
-  static_assert(std::is_same<const int&, decltype(ctaref)::reference>::value, "reference");
-  static_assert(std::is_same<const int*, decltype(ctaref)::const_pointer>::value, "const_pointer");
-  static_assert(std::is_same<const int&, decltype(ctaref)::const_reference>::value,
-                "const_reference");
+  static_assert(std::is_same_v<int, decltype(ctaref)::value_type>);
+  static_assert(std::is_same_v<const int*, decltype(ctaref)::pointer>);
+  static_assert(std::is_same_v<const int&, decltype(ctaref)::reference>);
+  static_assert(std::is_same_v<const int*, decltype(ctaref)::const_pointer>);
+  static_assert(std::is_same_v<const int&, decltype(ctaref)::const_reference>);
 
   std::copy(ctaref.begin(), ctaref.end(), std::back_inserter(output));
   ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
diff --git a/libartbase/base/transform_iterator.h b/libartbase/base/transform_iterator.h
index 5b0574d..062c88b 100644
--- a/libartbase/base/transform_iterator.h
+++ b/libartbase/base/transform_iterator.h
@@ -39,23 +39,20 @@
 template <typename BaseIterator, typename Function>
 class TransformIterator {
  private:
-  static_assert(std::is_base_of<
-                    std::input_iterator_tag,
-                    typename std::iterator_traits<BaseIterator>::iterator_category>::value,
+  static_assert(std::is_base_of_v<std::input_iterator_tag,
+                                  typename std::iterator_traits<BaseIterator>::iterator_category>,
                 "Transform iterator base must be an input iterator.");
 
   using InputType = typename std::iterator_traits<BaseIterator>::reference;
-  using ResultType = typename std::result_of<Function(InputType)>::type;
+  using ResultType = std::result_of_t<Function(InputType)>;
 
  public:
   using iterator_category = typename std::iterator_traits<BaseIterator>::iterator_category;
-  using value_type =
-      typename std::remove_const<typename std::remove_reference<ResultType>::type>::type;
+  using value_type = std::remove_const_t<std::remove_reference_t<ResultType>>;
   using difference_type = typename std::iterator_traits<BaseIterator>::difference_type;
-  using pointer = typename std::conditional<
-      std::is_reference<ResultType>::value,
-      typename std::add_pointer<typename std::remove_reference<ResultType>::type>::type,
-      TransformIterator>::type;
+  using pointer = std::conditional_t<std::is_reference_v<ResultType>,
+                                     std::add_pointer_t<std::remove_reference_t<ResultType>>,
+                                     TransformIterator>;
   using reference = ResultType;
 
   TransformIterator(BaseIterator base, Function fn)
@@ -78,10 +75,9 @@
   }
 
   TransformIterator& operator--() {
-    static_assert(
-        std::is_base_of<std::bidirectional_iterator_tag,
-                        typename std::iterator_traits<BaseIterator>::iterator_category>::value,
-        "BaseIterator must be bidirectional iterator to use operator--()");
+    static_assert(std::is_base_of_v<std::bidirectional_iterator_tag,
+                                    typename std::iterator_traits<BaseIterator>::iterator_category>,
+                  "BaseIterator must be bidirectional iterator to use operator--()");
     --data_.base_;
     return *this;
   }
@@ -97,34 +93,30 @@
   }
 
   reference operator[](difference_type n) const {
-    static_assert(
-        std::is_base_of<std::random_access_iterator_tag,
-                        typename std::iterator_traits<BaseIterator>::iterator_category>::value,
-        "BaseIterator must be random access iterator to use operator[]");
+    static_assert(std::is_base_of_v<std::random_access_iterator_tag,
+                                    typename std::iterator_traits<BaseIterator>::iterator_category>,
+                 "BaseIterator must be random access iterator to use operator[]");
     return GetFunction()(base()[n]);
   }
 
   TransformIterator operator+(difference_type n) const {
-    static_assert(
-        std::is_base_of<std::random_access_iterator_tag,
-                        typename std::iterator_traits<BaseIterator>::iterator_category>::value,
-        "BaseIterator must be random access iterator to use operator+");
+    static_assert(std::is_base_of_v<std::random_access_iterator_tag,
+                                    typename std::iterator_traits<BaseIterator>::iterator_category>,
+                  "BaseIterator must be random access iterator to use operator+");
     return TransformIterator(base() + n, GetFunction());
   }
 
   TransformIterator operator-(difference_type n) const {
-    static_assert(
-        std::is_base_of<std::random_access_iterator_tag,
-                        typename std::iterator_traits<BaseIterator>::iterator_category>::value,
-        "BaseIterator must be random access iterator to use operator-");
+    static_assert(std::is_base_of_v<std::random_access_iterator_tag,
+                                    typename std::iterator_traits<BaseIterator>::iterator_category>,
+                  "BaseIterator must be random access iterator to use operator-");
     return TransformIterator(base() - n, GetFunction());
   }
 
   difference_type operator-(const TransformIterator& other) const {
-    static_assert(
-        std::is_base_of<std::random_access_iterator_tag,
-                        typename std::iterator_traits<BaseIterator>::iterator_category>::value,
-        "BaseIterator must be random access iterator to use operator-");
+    static_assert(std::is_base_of_v<std::random_access_iterator_tag,
+                                    typename std::iterator_traits<BaseIterator>::iterator_category>,
+                  "BaseIterator must be random access iterator to use operator-");
     return base() - other.base();
   }
 
diff --git a/libartbase/base/transform_iterator_test.cc b/libartbase/base/transform_iterator_test.cc
index 5a5c37d..3d16465 100644
--- a/libartbase/base/transform_iterator_test.cc
+++ b/libartbase/base/transform_iterator_test.cc
@@ -45,32 +45,28 @@
   std::vector<int> output;
 
   using vector_titer = decltype(MakeTransformIterator(input.begin(), add1));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_titer::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_titer::value_type>::value, "value_type");
-  static_assert(std::is_same<vector_titer, vector_titer::pointer>::value, "pointer");
-  static_assert(std::is_same<int, vector_titer::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_titer::iterator_category>);
+  static_assert(std::is_same_v<int, vector_titer::value_type>);
+  static_assert(std::is_same_v<vector_titer, vector_titer::pointer>);
+  static_assert(std::is_same_v<int, vector_titer::reference>);
 
   using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), add1));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_ctiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_ctiter::value_type>::value, "value_type");
-  static_assert(std::is_same<vector_ctiter, vector_ctiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int, vector_ctiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_ctiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_ctiter::value_type>);
+  static_assert(std::is_same_v<vector_ctiter, vector_ctiter::pointer>);
+  static_assert(std::is_same_v<int, vector_ctiter::reference>);
 
   using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), add1));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_rtiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_rtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<vector_rtiter, vector_rtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int, vector_rtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_rtiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_rtiter::value_type>);
+  static_assert(std::is_same_v<vector_rtiter, vector_rtiter::pointer>);
+  static_assert(std::is_same_v<int, vector_rtiter::reference>);
 
   using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), add1));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_crtiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_crtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<vector_crtiter, vector_crtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int, vector_crtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_crtiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_crtiter::value_type>);
+  static_assert(std::is_same_v<vector_crtiter, vector_crtiter::pointer>);
+  static_assert(std::is_same_v<int, vector_crtiter::reference>);
 
   std::copy(MakeTransformIterator(input.begin(), add1),
             MakeTransformIterator(input.end(), add1),
@@ -134,11 +130,11 @@
   // Test iterator->const_iterator conversion and comparison.
   auto it = MakeTransformIterator(input.begin(), add1);
   decltype(MakeTransformIterator(input.cbegin(), add1)) cit = it;
-  static_assert(!std::is_same<decltype(it), decltype(cit)>::value, "Types must be different");
+  static_assert(!std::is_same_v<decltype(it), decltype(cit)>, "Types must be different");
   ASSERT_EQ(it, cit);
   auto rit = MakeTransformIterator(input.rbegin(), add1);
   decltype(MakeTransformIterator(input.crbegin(), add1)) crit(rit);
-  static_assert(!std::is_same<decltype(rit), decltype(crit)>::value, "Types must be different");
+  static_assert(!std::is_same_v<decltype(rit), decltype(crit)>, "Types must be different");
   ASSERT_EQ(rit, crit);
 }
 
@@ -148,32 +144,28 @@
   std::vector<int> output;
 
   using list_titer = decltype(MakeTransformIterator(input.begin(), sub1));
-  static_assert(std::is_same<std::bidirectional_iterator_tag,
-                             list_titer::iterator_category>::value, "category");
-  static_assert(std::is_same<int, list_titer::value_type>::value, "value_type");
-  static_assert(std::is_same<list_titer, list_titer::pointer>::value, "pointer");
-  static_assert(std::is_same<int, list_titer::reference>::value, "reference");
+  static_assert(std::is_same_v<std::bidirectional_iterator_tag, list_titer::iterator_category>);
+  static_assert(std::is_same_v<int, list_titer::value_type>);
+  static_assert(std::is_same_v<list_titer, list_titer::pointer>);
+  static_assert(std::is_same_v<int, list_titer::reference>);
 
   using list_ctiter = decltype(MakeTransformIterator(input.cbegin(), sub1));
-  static_assert(std::is_same<std::bidirectional_iterator_tag,
-                             list_ctiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, list_ctiter::value_type>::value, "value_type");
-  static_assert(std::is_same<list_ctiter, list_ctiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int, list_ctiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::bidirectional_iterator_tag, list_ctiter::iterator_category>);
+  static_assert(std::is_same_v<int, list_ctiter::value_type>);
+  static_assert(std::is_same_v<list_ctiter, list_ctiter::pointer>);
+  static_assert(std::is_same_v<int, list_ctiter::reference>);
 
   using list_rtiter = decltype(MakeTransformIterator(input.rbegin(), sub1));
-  static_assert(std::is_same<std::bidirectional_iterator_tag,
-                             list_rtiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, list_rtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<list_rtiter, list_rtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int, list_rtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::bidirectional_iterator_tag, list_rtiter::iterator_category>);
+  static_assert(std::is_same_v<int, list_rtiter::value_type>);
+  static_assert(std::is_same_v<list_rtiter, list_rtiter::pointer>);
+  static_assert(std::is_same_v<int, list_rtiter::reference>);
 
   using list_crtiter = decltype(MakeTransformIterator(input.crbegin(), sub1));
-  static_assert(std::is_same<std::bidirectional_iterator_tag,
-                             list_crtiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, list_crtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<list_crtiter, list_crtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int, list_crtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::bidirectional_iterator_tag, list_crtiter::iterator_category>);
+  static_assert(std::is_same_v<int, list_crtiter::value_type>);
+  static_assert(std::is_same_v<list_crtiter, list_crtiter::pointer>);
+  static_assert(std::is_same_v<int, list_crtiter::reference>);
 
   std::copy(MakeTransformIterator(input.begin(), sub1),
             MakeTransformIterator(input.end(), sub1),
@@ -202,7 +194,7 @@
   // Test iterator->const_iterator conversion and comparison.
   auto it = MakeTransformIterator(input.begin(), sub1);
   decltype(MakeTransformIterator(input.cbegin(), sub1)) cit = it;
-  static_assert(!std::is_same<decltype(it), decltype(cit)>::value, "Types must be different");
+  static_assert(!std::is_same_v<decltype(it), decltype(cit)>, "Types must be different");
   ASSERT_EQ(it, cit);
 }
 
@@ -212,18 +204,16 @@
   std::vector<int> output;
 
   using flist_titer = decltype(MakeTransformIterator(input.begin(), mul3));
-  static_assert(std::is_same<std::forward_iterator_tag,
-                             flist_titer::iterator_category>::value, "category");
-  static_assert(std::is_same<int, flist_titer::value_type>::value, "value_type");
-  static_assert(std::is_same<flist_titer, flist_titer::pointer>::value, "pointer");
-  static_assert(std::is_same<int, flist_titer::reference>::value, "reference");
+  static_assert(std::is_same_v<std::forward_iterator_tag, flist_titer::iterator_category>);
+  static_assert(std::is_same_v<int, flist_titer::value_type>);
+  static_assert(std::is_same_v<flist_titer, flist_titer::pointer>);
+  static_assert(std::is_same_v<int, flist_titer::reference>);
 
   using flist_ctiter = decltype(MakeTransformIterator(input.cbegin(), mul3));
-  static_assert(std::is_same<std::forward_iterator_tag,
-                             flist_ctiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, flist_ctiter::value_type>::value, "value_type");
-  static_assert(std::is_same<flist_ctiter, flist_ctiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int, flist_ctiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::forward_iterator_tag, flist_ctiter::iterator_category>);
+  static_assert(std::is_same_v<int, flist_ctiter::value_type>);
+  static_assert(std::is_same_v<flist_ctiter, flist_ctiter::pointer>);
+  static_assert(std::is_same_v<int, flist_ctiter::reference>);
 
   std::copy(MakeTransformIterator(input.begin(), mul3),
             MakeTransformIterator(input.end(), mul3),
@@ -240,7 +230,7 @@
   // Test iterator->const_iterator conversion and comparison.
   auto it = MakeTransformIterator(input.begin(), mul3);
   decltype(MakeTransformIterator(input.cbegin(), mul3)) cit = it;
-  static_assert(!std::is_same<decltype(it), decltype(cit)>::value, "Types must be different");
+  static_assert(!std::is_same_v<decltype(it), decltype(cit)>, "Types must be different");
   ASSERT_EQ(it, cit);
 }
 
@@ -250,32 +240,28 @@
   std::vector<int> output;
 
   using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_titer::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_titer::value_type>::value, "value_type");
-  static_assert(std::is_same<const int*, vector_titer::pointer>::value, "pointer");
-  static_assert(std::is_same<const int&, vector_titer::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_titer::iterator_category>);
+  static_assert(std::is_same_v<int, vector_titer::value_type>);
+  static_assert(std::is_same_v<const int*, vector_titer::pointer>);
+  static_assert(std::is_same_v<const int&, vector_titer::reference>);
 
   using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_ctiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_ctiter::value_type>::value, "value_type");
-  static_assert(std::is_same<const int*, vector_ctiter::pointer>::value, "pointer");
-  static_assert(std::is_same<const int&, vector_ctiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_ctiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_ctiter::value_type>);
+  static_assert(std::is_same_v<const int*, vector_ctiter::pointer>);
+  static_assert(std::is_same_v<const int&, vector_ctiter::reference>);
 
   using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_rtiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_rtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<const int*, vector_rtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<const int&, vector_rtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_rtiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_rtiter::value_type>);
+  static_assert(std::is_same_v<const int*, vector_rtiter::pointer>);
+  static_assert(std::is_same_v<const int&, vector_rtiter::reference>);
 
   using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_crtiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_crtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<const int*, vector_crtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<const int&, vector_crtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_crtiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_crtiter::value_type>);
+  static_assert(std::is_same_v<const int*, vector_crtiter::pointer>);
+  static_assert(std::is_same_v<const int&, vector_crtiter::reference>);
 
   std::copy(MakeTransformIterator(input.begin(), ref),
             MakeTransformIterator(input.end(), ref),
@@ -343,18 +329,16 @@
   std::vector<int> output;
 
   using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_titer::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_titer::value_type>::value, "value_type");
-  static_assert(std::is_same<int*, vector_titer::pointer>::value, "pointer");
-  static_assert(std::is_same<int&, vector_titer::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_titer::iterator_category>);
+  static_assert(std::is_same_v<int, vector_titer::value_type>);
+  static_assert(std::is_same_v<int*, vector_titer::pointer>);
+  static_assert(std::is_same_v<int&, vector_titer::reference>);
 
   using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_rtiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_rtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<int*, vector_rtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int&, vector_rtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_rtiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_rtiter::value_type>);
+  static_assert(std::is_same_v<int*, vector_rtiter::pointer>);
+  static_assert(std::is_same_v<int&, vector_rtiter::reference>);
 
   std::copy(MakeTransformIterator(input.begin(), ref),
             MakeTransformIterator(input.end(), ref),
@@ -411,32 +395,28 @@
   std::vector<int> output;
 
   using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_titer::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_titer::value_type>::value, "value_type");
-  static_assert(std::is_same<int*, vector_titer::pointer>::value, "pointer");
-  static_assert(std::is_same<int&, vector_titer::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_titer::iterator_category>);
+  static_assert(std::is_same_v<int, vector_titer::value_type>);
+  static_assert(std::is_same_v<int*, vector_titer::pointer>);
+  static_assert(std::is_same_v<int&, vector_titer::reference>);
 
   using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_ctiter::iterator_category>::value, "category");
-  // static_assert(std::is_same<int, vector_ctiter::value_type>::value, "value_type");
-  static_assert(std::is_same<const int*, vector_ctiter::pointer>::value, "pointer");
-  static_assert(std::is_same<const int&, vector_ctiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_ctiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_ctiter::value_type>);
+  static_assert(std::is_same_v<const int*, vector_ctiter::pointer>);
+  static_assert(std::is_same_v<const int&, vector_ctiter::reference>);
 
   using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_rtiter::iterator_category>::value, "category");
-  static_assert(std::is_same<int, vector_rtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<int*, vector_rtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<int&, vector_rtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_rtiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_rtiter::value_type>);
+  static_assert(std::is_same_v<int*, vector_rtiter::pointer>);
+  static_assert(std::is_same_v<int&, vector_rtiter::reference>);
 
   using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), ref));
-  static_assert(std::is_same<std::random_access_iterator_tag,
-                             vector_crtiter::iterator_category>::value, "category");
-  // static_assert(std::is_same<int, vector_crtiter::value_type>::value, "value_type");
-  static_assert(std::is_same<const int*, vector_crtiter::pointer>::value, "pointer");
-  static_assert(std::is_same<const int&, vector_crtiter::reference>::value, "reference");
+  static_assert(std::is_same_v<std::random_access_iterator_tag, vector_crtiter::iterator_category>);
+  static_assert(std::is_same_v<int, vector_crtiter::value_type>);
+  static_assert(std::is_same_v<const int*, vector_crtiter::pointer>);
+  static_assert(std::is_same_v<const int&, vector_crtiter::reference>);
 
   std::copy(MakeTransformIterator(input.begin(), ref),
             MakeTransformIterator(input.end(), ref),
@@ -500,11 +480,11 @@
   // Test iterator->const_iterator conversion and comparison.
   auto it = MakeTransformIterator(input.begin(), ref);
   decltype(MakeTransformIterator(input.cbegin(), ref)) cit = it;
-  static_assert(!std::is_same<decltype(it), decltype(cit)>::value, "Types must be different");
+  static_assert(!std::is_same_v<decltype(it), decltype(cit)>, "Types must be different");
   ASSERT_EQ(it, cit);
   auto rit = MakeTransformIterator(input.rbegin(), ref);
   decltype(MakeTransformIterator(input.crbegin(), ref)) crit(rit);
-  static_assert(!std::is_same<decltype(rit), decltype(crit)>::value, "Types must be different");
+  static_assert(!std::is_same_v<decltype(rit), decltype(crit)>, "Types must be different");
   ASSERT_EQ(rit, crit);
 
   // Test writing through the transform iterator.
diff --git a/libartbase/base/variant_map.h b/libartbase/base/variant_map.h
index 4244c9f..8d416e4 100644
--- a/libartbase/base/variant_map.h
+++ b/libartbase/base/variant_map.h
@@ -395,8 +395,7 @@
 
   template <typename TK, typename TValue, typename ... Rest>
   void InitializeParameters(const TK& key, const TValue& value, const Rest& ... rest) {
-    static_assert(
-        std::is_same<TK, TKey<TValue>>::value, "The 0th/2nd/4th/etc parameters must be a key");
+    static_assert(std::is_same_v<TK, TKey<TValue>>, "The 0th/2nd/4th/etc parameters must be a key");
 
     const TKey<TValue>& key_refined = key;
 
@@ -459,7 +458,7 @@
 
   template <typename TValue>
   static void StaticAssertKeyType() {
-    static_assert(std::is_base_of<VariantMapKey<TValue>, TKey<TValue>>::value,
+    static_assert(std::is_base_of_v<VariantMapKey<TValue>, TKey<TValue>>,
                   "The provided key type (TKey) must be a subclass of VariantMapKey");
   }