template_util.h revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
13aad3b01afc77993ff051c02e49186294e312980humper@google.com// Copyright (c) 2011 The Chromium Authors. All rights reserved.
23aad3b01afc77993ff051c02e49186294e312980humper@google.com// Use of this source code is governed by a BSD-style license that can be
33aad3b01afc77993ff051c02e49186294e312980humper@google.com// found in the LICENSE file.
43aad3b01afc77993ff051c02e49186294e312980humper@google.com
53aad3b01afc77993ff051c02e49186294e312980humper@google.com#ifndef BASE_TEMPLATE_UTIL_H_
63aad3b01afc77993ff051c02e49186294e312980humper@google.com#define BASE_TEMPLATE_UTIL_H_
73aad3b01afc77993ff051c02e49186294e312980humper@google.com
83aad3b01afc77993ff051c02e49186294e312980humper@google.com#include <cstddef>  // For size_t.
93aad3b01afc77993ff051c02e49186294e312980humper@google.com
103aad3b01afc77993ff051c02e49186294e312980humper@google.com#include "build/build_config.h"
113aad3b01afc77993ff051c02e49186294e312980humper@google.com
123aad3b01afc77993ff051c02e49186294e312980humper@google.comnamespace base {
133aad3b01afc77993ff051c02e49186294e312980humper@google.com
143aad3b01afc77993ff051c02e49186294e312980humper@google.com// template definitions from tr1
153aad3b01afc77993ff051c02e49186294e312980humper@google.com
163aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate<class T, T v>
177d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgstruct integral_constant {
183aad3b01afc77993ff051c02e49186294e312980humper@google.com  static const T value = v;
193aad3b01afc77993ff051c02e49186294e312980humper@google.com  typedef T value_type;
203aad3b01afc77993ff051c02e49186294e312980humper@google.com  typedef integral_constant<T, v> type;
213aad3b01afc77993ff051c02e49186294e312980humper@google.com};
223aad3b01afc77993ff051c02e49186294e312980humper@google.com
2377af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.comtemplate <class T, T v> const T integral_constant<T, v>::value;
243aad3b01afc77993ff051c02e49186294e312980humper@google.com
253aad3b01afc77993ff051c02e49186294e312980humper@google.comtypedef integral_constant<bool, true> true_type;
263aad3b01afc77993ff051c02e49186294e312980humper@google.comtypedef integral_constant<bool, false> false_type;
273aad3b01afc77993ff051c02e49186294e312980humper@google.com
287d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgtemplate <class T> struct is_pointer : false_type {};
297d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgtemplate <class T> struct is_pointer<T*> : true_type {};
307d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org
317d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgtemplate <class T, class U> struct is_same : public false_type {};
327d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgtemplate <class T> struct is_same<T,T> : true_type {};
333aad3b01afc77993ff051c02e49186294e312980humper@google.com
343aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate<class> struct is_array : public false_type {};
353aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate<class T, size_t n> struct is_array<T[n]> : public true_type {};
367d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgtemplate<class T> struct is_array<T[]> : public true_type {};
377d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org
387d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgtemplate <class T> struct is_non_const_reference : false_type {};
393aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate <class T> struct is_non_const_reference<T&> : true_type {};
403aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate <class T> struct is_non_const_reference<const T&> : false_type {};
413aad3b01afc77993ff051c02e49186294e312980humper@google.com
423aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate <class T> struct is_const : false_type {};
4377af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.comtemplate <class T> struct is_const<const T> : true_type {};
4477af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com
453aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate <class T> struct is_void : false_type {};
463aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate <> struct is_void<void> : true_type {};
473aad3b01afc77993ff051c02e49186294e312980humper@google.com
487d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgnamespace internal {
493aad3b01afc77993ff051c02e49186294e312980humper@google.com
503aad3b01afc77993ff051c02e49186294e312980humper@google.com// Types YesType and NoType are guaranteed such that sizeof(YesType) <
513aad3b01afc77993ff051c02e49186294e312980humper@google.com// sizeof(NoType).
5277af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.comtypedef char YesType;
533aad3b01afc77993ff051c02e49186294e312980humper@google.com
547d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgstruct NoType {
55a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org  YesType dummy[2];
5677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com};
573aad3b01afc77993ff051c02e49186294e312980humper@google.com
583aad3b01afc77993ff051c02e49186294e312980humper@google.com// This class is an implementation detail for is_convertible, and you
593aad3b01afc77993ff051c02e49186294e312980humper@google.com// don't need to know how it works to use is_convertible. For those
603aad3b01afc77993ff051c02e49186294e312980humper@google.com// who care: we declare two different functions, one whose argument is
613aad3b01afc77993ff051c02e49186294e312980humper@google.com// of type To and one with a variadic argument list. We give them
623aad3b01afc77993ff051c02e49186294e312980humper@google.com// return types of different size, so we can use sizeof to trick the
633aad3b01afc77993ff051c02e49186294e312980humper@google.com// compiler into telling us which function it would have chosen if we
643aad3b01afc77993ff051c02e49186294e312980humper@google.com// had called it with an argument of type From.  See Alexandrescu's
653aad3b01afc77993ff051c02e49186294e312980humper@google.com// _Modern C++ Design_ for more details on this sort of trick.
663aad3b01afc77993ff051c02e49186294e312980humper@google.com
673aad3b01afc77993ff051c02e49186294e312980humper@google.comstruct ConvertHelper {
683aad3b01afc77993ff051c02e49186294e312980humper@google.com  template <typename To>
693aad3b01afc77993ff051c02e49186294e312980humper@google.com  static YesType Test(To);
703aad3b01afc77993ff051c02e49186294e312980humper@google.com
713aad3b01afc77993ff051c02e49186294e312980humper@google.com  template <typename To>
723aad3b01afc77993ff051c02e49186294e312980humper@google.com  static NoType Test(...);
733aad3b01afc77993ff051c02e49186294e312980humper@google.com
743aad3b01afc77993ff051c02e49186294e312980humper@google.com  template <typename From>
753aad3b01afc77993ff051c02e49186294e312980humper@google.com  static From& Create();
763aad3b01afc77993ff051c02e49186294e312980humper@google.com};
773aad3b01afc77993ff051c02e49186294e312980humper@google.com
783aad3b01afc77993ff051c02e49186294e312980humper@google.com// Used to determine if a type is a struct/union/class. Inspired by Boost's
793aad3b01afc77993ff051c02e49186294e312980humper@google.com// is_class type_trait implementation.
803aad3b01afc77993ff051c02e49186294e312980humper@google.comstruct IsClassHelper {
813aad3b01afc77993ff051c02e49186294e312980humper@google.com  template <typename C>
823aad3b01afc77993ff051c02e49186294e312980humper@google.com  static YesType Test(void(C::*)(void));
83dec61503d02862760f3c91203a698636a02c882acommit-bot@chromium.org
84dec61503d02862760f3c91203a698636a02c882acommit-bot@chromium.org  template <typename C>
85dec61503d02862760f3c91203a698636a02c882acommit-bot@chromium.org  static NoType Test(...);
86dec61503d02862760f3c91203a698636a02c882acommit-bot@chromium.org};
87dec61503d02862760f3c91203a698636a02c882acommit-bot@chromium.org
88dec61503d02862760f3c91203a698636a02c882acommit-bot@chromium.org}  // namespace internal
89dec61503d02862760f3c91203a698636a02c882acommit-bot@chromium.org
90dec61503d02862760f3c91203a698636a02c882acommit-bot@chromium.org// Inherits from true_type if From is convertible to To, false_type otherwise.
917d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org//
923aad3b01afc77993ff051c02e49186294e312980humper@google.com// Note that if the type is convertible, this will be a true_type REGARDLESS
933aad3b01afc77993ff051c02e49186294e312980humper@google.com// of whether or not the conversion would emit a warning.
943aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate <typename From, typename To>
953aad3b01afc77993ff051c02e49186294e312980humper@google.comstruct is_convertible
967d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org    : integral_constant<bool,
977d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org                        sizeof(internal::ConvertHelper::Test<To>(
987d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org                                   internal::ConvertHelper::Create<From>())) ==
993aad3b01afc77993ff051c02e49186294e312980humper@google.com                        sizeof(internal::YesType)> {
1007d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org};
1013aad3b01afc77993ff051c02e49186294e312980humper@google.com
1027d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgtemplate <typename T>
1037d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgstruct is_class
1047d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org    : integral_constant<bool,
1053aad3b01afc77993ff051c02e49186294e312980humper@google.com                        sizeof(internal::IsClassHelper::Test<T>(0)) ==
1063aad3b01afc77993ff051c02e49186294e312980humper@google.com                            sizeof(internal::YesType)> {
1073aad3b01afc77993ff051c02e49186294e312980humper@google.com};
1083aad3b01afc77993ff051c02e49186294e312980humper@google.com
1093aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate<bool B, class T = void>
1107d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.orgstruct enable_if {};
1113aad3b01afc77993ff051c02e49186294e312980humper@google.com
1123aad3b01afc77993ff051c02e49186294e312980humper@google.comtemplate<class T>
1133aad3b01afc77993ff051c02e49186294e312980humper@google.comstruct enable_if<true, T> { typedef T type; };
114d3baf20dd1de9940717dd50b5c9ff6061561342ecommit-bot@chromium.org
1153aad3b01afc77993ff051c02e49186294e312980humper@google.com}  // namespace base
1167d7f31433b627e62f518e9186d3f2d9bd44662e0commit-bot@chromium.org
1173aad3b01afc77993ff051c02e49186294e312980humper@google.com#endif  // BASE_TEMPLATE_UTIL_H_
1183aad3b01afc77993ff051c02e49186294e312980humper@google.com