1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef BASE_TEMPLATE_UTIL_H_
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define BASE_TEMPLATE_UTIL_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <cstddef>  // For size_t.
1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "build/build_config.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace base {
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// template definitions from tr1
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate<class T, T v>
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct integral_constant {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const T value = v;
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef T value_type;
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef integral_constant<T, v> type;
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <class T, T v> const T integral_constant<T, v>::value;
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef integral_constant<bool, true> true_type;
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef integral_constant<bool, false> false_type;
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <class T> struct is_pointer : false_type {};
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <class T> struct is_pointer<T*> : true_type {};
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentemplate<class> struct is_array : public false_type {};
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentemplate<class T, size_t n> struct is_array<T[n]> : public true_type {};
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentemplate<class T> struct is_array<T[]> : public true_type {};
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentemplate <class T> struct is_non_const_reference : false_type {};
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentemplate <class T> struct is_non_const_reference<T&> : true_type {};
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentemplate <class T> struct is_non_const_reference<const T&> : false_type {};
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace internal {
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Types YesType and NoType are guaranteed such that sizeof(YesType) <
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// sizeof(NoType).
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentypedef char YesType;
4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstruct NoType {
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  YesType dummy[2];
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// This class is an implementation detail for is_convertible, and you
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// don't need to know how it works to use is_convertible. For those
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// who care: we declare two different functions, one whose argument is
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// of type To and one with a variadic argument list. We give them
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// return types of different size, so we can use sizeof to trick the
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// compiler into telling us which function it would have chosen if we
5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// had called it with an argument of type From.  See Alexandrescu's
5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// _Modern C++ Design_ for more details on this sort of trick.
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstruct ConvertHelper {
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  template <typename To>
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static YesType Test(To);
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  template <typename To>
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static NoType Test(...);
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  template <typename From>
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  static From Create();
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Used to determine if a type is a struct/union/class. Inspired by Boost's
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// is_class type_trait implementation.
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstruct IsClassHelper {
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  template <typename C>
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static YesType Test(void(C::*)(void));
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  template <typename C>
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static NoType Test(...);
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace internal
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Inherits from true_type if From is convertible to To, false_type otherwise.
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen//
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Note that if the type is convertible, this will be a true_type REGARDLESS
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// of whether or not the conversion would emit a warning.
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsentemplate <typename From, typename To>
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstruct is_convertible
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : integral_constant<bool,
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                        sizeof(internal::ConvertHelper::Test<To>(
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   internal::ConvertHelper::Create<From>())) ==
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                        sizeof(internal::YesType)> {
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentemplate <typename T>
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstruct is_class
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : integral_constant<bool,
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        sizeof(internal::IsClassHelper::Test<T>(0)) ==
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                            sizeof(internal::YesType)> {
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace base
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif  // BASE_TEMPLATE_UTIL_H_
104