/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Template-based metaprogramming and type-testing facilities. */ #ifndef mozilla_TypeTraits_h_ #define mozilla_TypeTraits_h_ /* * These traits are approximate copies of the traits and semantics from C++11's * header. Don't add traits not in that header! When all * platforms provide that header, we can convert all users and remove this one. */ #include namespace mozilla { /** * Helper class used as a base for various type traits, exposed publicly * because exposes it as well. */ template struct IntegralConstant { static const T value = Value; typedef T ValueType; typedef IntegralConstant Type; }; /** Convenient aliases. */ typedef IntegralConstant TrueType; typedef IntegralConstant FalseType; namespace detail { // The trickery used to implement IsBaseOf here makes it possible to use it for // the cases of private and multiple inheritance. This code was inspired by the // sample code here: // // http://stackoverflow.com/questions/2910979/how-is-base-of-works template struct BaseOfHelper { public: operator Base*() const; operator Derived*(); }; template struct BaseOfTester { private: template static char test(Derived*, T); static int test(Base*, int); public: static const bool value = sizeof(test(BaseOfHelper(), int())) == sizeof(char); }; template struct BaseOfTester { private: template static char test(Derived*, T); static int test(Base*, int); public: static const bool value = sizeof(test(BaseOfHelper(), int())) == sizeof(char); }; template struct BaseOfTester : FalseType {}; template struct BaseOfTester : TrueType {}; template struct BaseOfTester : TrueType {}; } /* namespace detail */ template struct Conditional; /* * IsBaseOf allows to know whether a given class is derived from another. * * Consider the following class definitions: * * class A {}; * class B : public A {}; * class C {}; * * mozilla::IsBaseOf::value is true; * mozilla::IsBaseOf::value is false; */ template struct IsBaseOf : Conditional::value, TrueType, FalseType>::Type {}; namespace detail { template struct ConvertibleTester { private: static From create(); template static char test(To to); template static int test(...); public: static const bool value = sizeof(test(create())) == sizeof(char); }; } // namespace detail /** * IsConvertible determines whether a value of type From will implicitly convert * to a value of type To. For example: * * struct A {}; * struct B : public A {}; * struct C {}; * * mozilla::IsConvertible::value is true; * mozilla::IsConvertible::value is true; * mozilla::IsConvertible::value is true; * mozilla::IsConvertible::value is true; * mozilla::IsConvertible::value is false; * mozilla::IsConvertible::value is false; * mozilla::IsConvertible::value is false; * mozilla::IsConvertible::value is false. * * For obscure reasons, you can't use IsConvertible when the types being tested * are related through private inheritance, and you'll get a compile error if * you try. Just don't do it! */ template struct IsConvertible : Conditional::value, TrueType, FalseType>::Type {}; /** * Conditional selects a class between two, depending on a given boolean value. * * mozilla::Conditional::Type is A; * mozilla::Conditional::Type is B; */ template struct Conditional { typedef A Type; }; template struct Conditional { typedef B Type; }; /** * EnableIf is a struct containing a typedef of T if and only if B is true. * * mozilla::EnableIf::Type is int; * mozilla::EnableIf::Type is a compile-time error. * * Use this template to implement SFINAE-style (Substitution Failure Is not An * Error) requirements. For example, you might use it to impose a restriction * on a template parameter: * * template * class PodVector // vector optimized to store POD (memcpy-able) types * { * EnableIf::value, T>::Type* vector; * size_t length; * ... * }; */ template struct EnableIf {}; template struct EnableIf { typedef T Type; }; /** * IsSame tests whether two types are the same type. * * mozilla::IsSame::value is true; * mozilla::IsSame::value is true; * mozilla::IsSame::value is false; * mozilla::IsSame::value is true; * mozilla::IsSame::value is false; * mozilla::IsSame::value is true. */ template struct IsSame : FalseType {}; template struct IsSame : TrueType {}; /** * Traits class for identifying POD types. Until C++11 there's no automatic * way to detect PODs, so for the moment this is done manually. Users may * define specializations of this class that inherit from mozilla::TrueType and * mozilla::FalseType (or equivalently mozilla::IntegralConstant, or conveniently from mozilla::IsPod for composite types) as needed to * ensure correct IsPod behavior. */ template struct IsPod : public FalseType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template<> struct IsPod : TrueType {}; template struct IsPod : TrueType {}; /** * IsPointer determines whether a type is a pointer type (but not a pointer-to- * member type). * * mozilla::IsPointer::value is true; * mozilla::IsPointer::value is true; * mozilla::IsPointer::value is true; * mozilla::IsPointer::value is false; * mozilla::IsPointer::value is false. */ template struct IsPointer : FalseType {}; template struct IsPointer : TrueType {}; } /* namespace mozilla */ #endif /* mozilla_TypeTraits_h_ */