#pragma once

#include <stdtypedefs.h>

namespace std {
  template<class T, T v>
  struct integral_constant {
    static constexpr T value = v;
    typedef T value_type;
    constexpr operator value_type() const noexcept { return value; }
    constexpr value_type operator()() const noexcept { return value; }
  };

  typedef integral_constant<bool, true> true_type;
  typedef integral_constant<bool, false> false_type;

  template<class T, class U>
  struct is_same : std::false_type {};

  template<class T>
  struct is_same<T, T> : std::true_type {};

  template<class T>
  struct is_void : std::false_type {};

  template<>
  struct is_void<void> : std::true_type {};

  template<class T>
  struct is_enum : integral_constant<bool, __is_enum(T)> {};

  template<class T>
  struct is_union : integral_constant<bool, __is_union(T)> {};

  template<class T>
  struct is_class : integral_constant<bool, __is_class(T)> {};

  template<class T>
  struct is_fundamental : integral_constant<bool, __is_fundamental(T)> {};

  template<class T>
  struct is_compound : integral_constant<bool, !__is_fundamental(T)> {};

  template<class T>
  struct is_trivial : integral_constant<bool, __is_trivial(T)> {};

  template<class T>
  struct is_standard_layout : integral_constant<bool, __is_standard_layout(T)> {};

  template<class T>
  struct is_pod : integral_constant<bool, __is_pod(T)> {};

  template<class T>
  struct is_empty : integral_constant<bool, __is_empty(T)> {};

  template<class T>
  struct is_polymorphic : integral_constant<bool, __is_polymorphic(T)> {};

  template<class T>
  struct is_abstract : integral_constant<bool, __is_abstract(T)> {};

  template<class T>
  struct is_final : integral_constant<bool, __is_final(T)> {};

  template<class T>
  struct is_default_constructible : integral_constant<bool, __is_constructible(T)> {};

  template<class T>
  struct is_copy_constructible : integral_constant<bool, __is_constructible(T, const T&)> {};

  template<class T>
  struct is_move_constructible : integral_constant<bool, __is_constructible(T, const T&&)> {};

  template<class T>
  struct is_destructible : integral_constant<bool, __is_destructible(T)> {};

  template<class T>
  struct has_virtual_destructor : integral_constant<bool, __has_virtual_destructor(T)> {};

  template<class T >
  struct alignment_of : std::integral_constant<std::size_t, alignof(T)> {};

  template<class T, class U>
  struct is_base_of : integral_constant<bool, __is_base_of(T, U)> {};

  template<class T, class U>
  struct is_convertible : integral_constant<bool, __is_convertible_to(T, U)> {};

  template<class T> struct add_cv { typedef const volatile T type; };
  template<class T> struct add_const { typedef const T type; };
  template<class T> struct add_volatile { typedef volatile T type; };

  template<class T> struct add_lvalue_reference { typedef T &type; };
  template<class T> struct add_rvalue_reference { typedef T &&type; };
  template<class T> struct add_pointer { typedef T *type; };
}
