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