13f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// Copyright (c) 2011 The Chromium Authors. All rights reserved.
23f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// Use of this source code is governed by a BSD-style license that can be
33f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// found in the LICENSE file.
4cd9fa24dde8d32cc1c207db9e96d48f6c6d9b45frouslan@chromium.org//
5cd9fa24dde8d32cc1c207db9e96d48f6c6d9b45frouslan@chromium.org// The original source code is from:
6cd9fa24dde8d32cc1c207db9e96d48f6c6d9b45frouslan@chromium.org// https://code.google.com/p/libphonenumber/source/browse/trunk/cpp/src/phonenumbers/base/template_util.h?r=621
73f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
8cd9fa24dde8d32cc1c207db9e96d48f6c6d9b45frouslan@chromium.org#ifndef I18N_ADDRESSINPUT_UTIL_TEMPLATE_UTIL_H_
9cd9fa24dde8d32cc1c207db9e96d48f6c6d9b45frouslan@chromium.org#define I18N_ADDRESSINPUT_UTIL_TEMPLATE_UTIL_H_
103f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
113f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org#include <cstddef>  // For size_t.
123f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
133f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgnamespace i18n {
14cd9fa24dde8d32cc1c207db9e96d48f6c6d9b45frouslan@chromium.orgnamespace addressinput {
153f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
163f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// template definitions from tr1
173f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
183f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate<class T, T v>
193f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgstruct integral_constant {
203f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  static const T value = v;
213f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  typedef T value_type;
223f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  typedef integral_constant<T, v> type;
233f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org};
243f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
253f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T, T v> const T integral_constant<T, v>::value;
263f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
273f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtypedef integral_constant<bool, true> true_type;
283f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtypedef integral_constant<bool, false> false_type;
293f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
303f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T> struct is_pointer : false_type {};
313f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T> struct is_pointer<T*> : true_type {};
323f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
333f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T, class U> struct is_same : public false_type {};
343f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T> struct is_same<T,T> : true_type {};
353f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
363f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate<class> struct is_array : public false_type {};
373f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate<class T, size_t n> struct is_array<T[n]> : public true_type {};
383f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate<class T> struct is_array<T[]> : public true_type {};
393f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
403f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T> struct is_non_const_reference : false_type {};
413f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T> struct is_non_const_reference<T&> : true_type {};
423f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T> struct is_non_const_reference<const T&> : false_type {};
433f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
443f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <class T> struct is_void : false_type {};
453f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <> struct is_void<void> : true_type {};
463f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
473f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgnamespace internal {
483f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
493f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// Types YesType and NoType are guaranteed such that sizeof(YesType) <
503f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// sizeof(NoType).
513f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtypedef char YesType;
523f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
533f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgstruct NoType {
543f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  YesType dummy[2];
553f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org};
563f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
573f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// This class is an implementation detail for is_convertible, and you
583f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// don't need to know how it works to use is_convertible. For those
593f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// who care: we declare two different functions, one whose argument is
603f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// of type To and one with a variadic argument list. We give them
613f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// return types of different size, so we can use sizeof to trick the
623f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// compiler into telling us which function it would have chosen if we
633f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// had called it with an argument of type From.  See Alexandrescu's
643f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// _Modern C++ Design_ for more details on this sort of trick.
653f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
663f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgstruct ConvertHelper {
673f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  template <typename To>
683f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  static YesType Test(To);
693f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
703f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  template <typename To>
713f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  static NoType Test(...);
723f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
733f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  template <typename From>
743f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  static From& Create();
753f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org};
763f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
773f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// Used to determine if a type is a struct/union/class. Inspired by Boost's
783f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// is_class type_trait implementation.
793f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgstruct IsClassHelper {
803f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  template <typename C>
813f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  static YesType Test(void(C::*)(void));
823f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
833f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  template <typename C>
843f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org  static NoType Test(...);
853f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org};
863f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
873f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org}  // namespace internal
883f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
893f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// Inherits from true_type if From is convertible to To, false_type otherwise.
903f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org//
913f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// Note that if the type is convertible, this will be a true_type REGARDLESS
923f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org// of whether or not the conversion would emit a warning.
933f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <typename From, typename To>
943f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgstruct is_convertible
953f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org    : integral_constant<bool,
963f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org                        sizeof(internal::ConvertHelper::Test<To>(
973f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org                                   internal::ConvertHelper::Create<From>())) ==
983f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org                        sizeof(internal::YesType)> {
993f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org};
1003f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
1013f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgtemplate <typename T>
1023f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.orgstruct is_class
1033f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org    : integral_constant<bool,
1043f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org                        sizeof(internal::IsClassHelper::Test<T>(0)) ==
1053f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org                            sizeof(internal::YesType)> {
1063f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org};
1073f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
108cd9fa24dde8d32cc1c207db9e96d48f6c6d9b45frouslan@chromium.org}  // namespace addressinput
1093f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org}  // namespace i18n
1103f951fab4e50260c90a94b75c8a56912828f1fadrouslan@chromium.org
111cd9fa24dde8d32cc1c207db9e96d48f6c6d9b45frouslan@chromium.org#endif  // I18N_ADDRESSINPUT_UTIL_TEMPLATE_UTIL_H_
112