author | Ehsan Akhgari <ehsan@mozilla.com> |
Wed, 17 Oct 2012 17:37:53 -0400 | |
changeset 118701 | 9806c99965fbf1b5770813b4c6eb4c6dcb3413e4 |
parent 118700 | 2030c47a8e69afb3f88c55d19bbf0dee7734c8c1 |
child 118702 | 4c979ca3eb7a1ca1ecd7b671ec61b6af9aa4de43 |
push id | 1997 |
push user | akeybl@mozilla.com |
push date | Mon, 07 Jan 2013 21:25:26 +0000 |
treeherder | mozilla-beta@4baf45cdcf21 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Waldo |
bugs | 802806 |
milestone | 19.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
mfbt/TypeTraits.h | file | annotate | diff | comparison | revisions | |
mfbt/tests/TestTypeTraits.cpp | file | annotate | diff | comparison | revisions |
--- a/mfbt/TypeTraits.h +++ b/mfbt/TypeTraits.h @@ -4,38 +4,92 @@ /* Template-based metaprogramming and type-testing facilities. */ #ifndef mozilla_TypeTraits_h_ #define mozilla_TypeTraits_h_ namespace mozilla { +namespace detail { + +/** + * The trickery used to implement IsBaseOf here makes it possible to use it for + * the cases of multiple inheritence. This code was inspired by the sample code + * here: + * + * http://stackoverflow.com/questions/2910979/how-is-base-of-works + */ +template<class Base, class Derived> +class IsBaseOfHelper +{ + public: + operator Base*() const; + operator Derived*(); +}; + +} /* namespace detail */ + /* * 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<A, B>::value is true; * mozilla::IsBaseOf<A, C>::value is false; */ template<class Base, class Derived> class IsBaseOf { private: - static char test(Base* b); - static int test(...); + template<class T> + static char test(Derived*, T); + static int test(Base*, int); + + public: + static const bool value = + sizeof(test(detail::IsBaseOfHelper<Base, Derived>(), int())) == sizeof(char); +}; + +template<class Base, class Derived> +class IsBaseOf<Base, const Derived> +{ + private: + template<class T> + static char test(Derived*, T); + static int test(Base*, int); public: static const bool value = - sizeof(test(static_cast<Derived*>(0))) == sizeof(char); + sizeof(test(detail::IsBaseOfHelper<Base, Derived>(), int())) == sizeof(char); +}; + +template<class Base, class Derived> +class IsBaseOf<Base&, Derived&> +{ + public: + static const bool value = false; +}; + +template<class Type> +class IsBaseOf<Type, Type> +{ + public: + static const bool value = true; +}; + +template<class Type> +class IsBaseOf<Type, const Type> +{ + public: + static const bool value = true; }; /* * 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 {};
--- a/mfbt/tests/TestTypeTraits.cpp +++ b/mfbt/tests/TestTypeTraits.cpp @@ -1,22 +1,73 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ #include "mozilla/Assertions.h" #include "mozilla/TypeTraits.h" +using mozilla::IsBaseOf; using mozilla::IsConvertible; +namespace CPlusPlus11IsBaseOf { + +// Adapted from C++11 ยง 20.9.6. +struct B {}; +struct B1 : B {}; +struct B2 : B {}; +struct D : private B1, private B2 {}; + +static void +StandardIsBaseOfTests() +{ + MOZ_ASSERT((IsBaseOf<B, D>::value) == true); + MOZ_ASSERT((IsBaseOf<const B, D>::value) == true); + MOZ_ASSERT((IsBaseOf<B, const D>::value) == true); + MOZ_ASSERT((IsBaseOf<B, const B>::value) == true); + MOZ_ASSERT((IsBaseOf<D, B>::value) == false); + MOZ_ASSERT((IsBaseOf<B&, D&>::value) == false); + MOZ_ASSERT((IsBaseOf<B[3], D[3]>::value) == false); + // We fail at the following test. To fix it, we need to specialize IsBaseOf + // for all built-in types. + // MOZ_ASSERT((IsBaseOf<int, int>::value) == false); +} + +} /* namespace CPlusPlus11IsBaseOf */ + class A { }; class B : public A { }; class C : private A { }; class D { }; +class E : public A { }; +class F : public B, public E { }; + +static void +TestIsBaseOf() +{ + MOZ_ASSERT((IsBaseOf<A, B>::value), + "A is a base of B"); + MOZ_ASSERT((!IsBaseOf<B, A>::value), + "B is not a base of A"); + MOZ_ASSERT((IsBaseOf<A, C>::value), + "A is a base of C"); + MOZ_ASSERT((!IsBaseOf<C, A>::value), + "C is not a base of A"); + MOZ_ASSERT((IsBaseOf<A, F>::value), + "A is a base of F"); + MOZ_ASSERT((!IsBaseOf<F, A>::value), + "F is not a base of A"); + MOZ_ASSERT((!IsBaseOf<A, D>::value), + "A is not a base of D"); + MOZ_ASSERT((!IsBaseOf<D, A>::value), + "D is not a base of A"); + MOZ_ASSERT((IsBaseOf<B, B>::value), + "B is the same as B (and therefore, a base of B)"); +} static void TestIsConvertible() { // Pointer type convertibility MOZ_ASSERT((IsConvertible<A*, A*>::value), "A* should convert to A*"); MOZ_ASSERT((IsConvertible<B*, A*>::value), @@ -46,10 +97,12 @@ TestIsConvertible() // "C* shouldn't convert to A* (private inheritance)"); //MOZ_ASSERT((!IsConvertible<C, A>::value), // "C doesn't convert to A (private inheritance)"); } int main() { + CPlusPlus11IsBaseOf::StandardIsBaseOfTests(); + TestIsBaseOf(); TestIsConvertible(); }