michael@0: // Copyright (c) 2011 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef BASE_TEMPLATE_UTIL_H_ michael@0: #define BASE_TEMPLATE_UTIL_H_ michael@0: michael@0: #include // For size_t. michael@0: michael@0: #include "build/build_config.h" michael@0: michael@0: namespace base { michael@0: michael@0: // template definitions from tr1 michael@0: michael@0: template michael@0: struct integral_constant { michael@0: static const T value = v; michael@0: typedef T value_type; michael@0: typedef integral_constant type; michael@0: }; michael@0: michael@0: template const T integral_constant::value; michael@0: michael@0: typedef integral_constant true_type; michael@0: typedef integral_constant false_type; michael@0: michael@0: template struct is_pointer : false_type {}; michael@0: template struct is_pointer : true_type {}; michael@0: michael@0: template struct is_same : public false_type {}; michael@0: template struct is_same : true_type {}; michael@0: michael@0: template struct is_array : public false_type {}; michael@0: template struct is_array : public true_type {}; michael@0: template struct is_array : public true_type {}; michael@0: michael@0: template struct is_non_const_reference : false_type {}; michael@0: template struct is_non_const_reference : true_type {}; michael@0: template struct is_non_const_reference : false_type {}; michael@0: michael@0: template struct is_void : false_type {}; michael@0: template <> struct is_void : true_type {}; michael@0: michael@0: namespace internal { michael@0: michael@0: // Types YesType and NoType are guaranteed such that sizeof(YesType) < michael@0: // sizeof(NoType). michael@0: typedef char YesType; michael@0: michael@0: struct NoType { michael@0: YesType dummy[2]; michael@0: }; michael@0: michael@0: // This class is an implementation detail for is_convertible, and you michael@0: // don't need to know how it works to use is_convertible. For those michael@0: // who care: we declare two different functions, one whose argument is michael@0: // of type To and one with a variadic argument list. We give them michael@0: // return types of different size, so we can use sizeof to trick the michael@0: // compiler into telling us which function it would have chosen if we michael@0: // had called it with an argument of type From. See Alexandrescu's michael@0: // _Modern C++ Design_ for more details on this sort of trick. michael@0: michael@0: struct ConvertHelper { michael@0: template michael@0: static YesType Test(To); michael@0: michael@0: template michael@0: static NoType Test(...); michael@0: michael@0: template michael@0: static From& Create(); michael@0: }; michael@0: michael@0: // Used to determine if a type is a struct/union/class. Inspired by Boost's michael@0: // is_class type_trait implementation. michael@0: struct IsClassHelper { michael@0: template michael@0: static YesType Test(void(C::*)(void)); michael@0: michael@0: template michael@0: static NoType Test(...); michael@0: }; michael@0: michael@0: } // namespace internal michael@0: michael@0: // Inherits from true_type if From is convertible to To, false_type otherwise. michael@0: // michael@0: // Note that if the type is convertible, this will be a true_type REGARDLESS michael@0: // of whether or not the conversion would emit a warning. michael@0: template michael@0: struct is_convertible michael@0: : integral_constant( michael@0: internal::ConvertHelper::Create())) == michael@0: sizeof(internal::YesType)> { michael@0: }; michael@0: michael@0: template michael@0: struct is_class michael@0: : integral_constant(0)) == michael@0: sizeof(internal::YesType)> { michael@0: }; michael@0: michael@0: } // namespace base michael@0: michael@0: #endif // BASE_TEMPLATE_UTIL_H_