1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_
6#define MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_
7
8namespace mojo {
9namespace internal {
10
11template<class T, T v>
12struct IntegralConstant {
13  static const T value = v;
14};
15
16template <class T, T v> const T IntegralConstant<T, v>::value;
17
18typedef IntegralConstant<bool, true> TrueType;
19typedef IntegralConstant<bool, false> FalseType;
20
21template <class T> struct IsConst : FalseType {};
22template <class T> struct IsConst<const T> : TrueType {};
23
24template<bool B, typename T = void>
25struct EnableIf {};
26
27template<typename T>
28struct EnableIf<true, T> { typedef T type; };
29
30// Types YesType and NoType are guaranteed such that sizeof(YesType) <
31// sizeof(NoType).
32typedef char YesType;
33
34struct NoType {
35  YesType dummy[2];
36};
37
38// A helper template to determine if given type is non-const move-only-type,
39// i.e. if a value of the given type should be passed via .Pass() in a
40// destructive way.
41template <typename T> struct IsMoveOnlyType {
42  template <typename U>
43  static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
44
45  template <typename U>
46  static NoType Test(...);
47
48  static const bool value = sizeof(Test<T>(0)) == sizeof(YesType) &&
49                            !IsConst<T>::value;
50};
51
52template <typename T>
53typename EnableIf<!IsMoveOnlyType<T>::value, T>::type& Forward(T& t) {
54  return t;
55}
56
57template <typename T>
58typename EnableIf<IsMoveOnlyType<T>::value, T>::type Forward(T& t) {
59  return t.Pass();
60}
61
62// This goop is a trick used to implement a template that can be used to
63// determine if a given class is the base class of another given class.
64template<typename, typename> struct IsSame {
65  static bool const value = false;
66};
67template<typename A> struct IsSame<A, A> {
68  static bool const value = true;
69};
70template<typename Base, typename Derived> struct IsBaseOf {
71 private:
72  // This class doesn't work correctly with forward declarations.
73  // Because sizeof cannot be applied to incomplete types, this line prevents us
74  // from passing in forward declarations.
75  typedef char (*EnsureTypesAreComplete)[sizeof(Base) + sizeof(Derived)];
76
77  static Derived* CreateDerived();
78  static char (&Check(Base*))[1];
79  static char (&Check(...))[2];
80
81 public:
82  static bool const value = sizeof Check(CreateDerived()) == 1 &&
83                            !IsSame<Base const, void const>::value;
84};
85
86}  // namespace internal
87}  // namespace mojo
88
89#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_
90