Bug 766347 - Implement mozilla::IsConvertible to detect when a value of one type will convert to a value of another type. r=luke

--HG--
extra : rebase_source : d25c1b84dfc928a0bc4dcfb43e31b6035882849e
This commit is contained in:
Jeff Walden 2012-06-19 13:55:23 -07:00
Родитель 6c37b7fa4b
Коммит a8690eb7c8
3 изменённых файлов: 97 добавлений и 1 удалений

Просмотреть файл

@ -27,8 +27,48 @@ class IsBaseOf
private:
static char test(Base* b);
static int test(...);
public:
static const bool value = (sizeof(test(static_cast<Derived*>(0))) == sizeof(char));
static const bool value =
sizeof(test(static_cast<Derived*>(0))) == sizeof(char);
};
/*
* 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<A, A>::value is true;
* mozilla::IsConvertible<A*, A*>::value is true;
* mozilla::IsConvertible<B, A>::value is true;
* mozilla::IsConvertible<B*, A*>::value is true;
* mozilla::IsConvertible<C, A>::value is false;
* mozilla::IsConvertible<A, C>::value is false;
* mozilla::IsConvertible<A*, C*>::value is false;
* mozilla::IsConvertible<C*, A*>::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<typename From, typename To>
struct IsConvertible
{
private:
static From create();
template<typename From1, typename To1>
static char test(To to);
template<typename From1, typename To1>
static int test(...);
public:
static const bool value =
sizeof(test<From, To>(create())) == sizeof(char);
};
/*

Просмотреть файл

@ -13,6 +13,7 @@ STL_FLAGS =
CPP_UNIT_TESTS = \
TestCheckedInt.cpp \
TestTypeTraits.cpp \
$(NULL)
# in order to prevent rules.mk from trying to link to libraries that are

Просмотреть файл

@ -0,0 +1,55 @@
/* -*- 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::IsConvertible;
class A { };
class B : public A { };
class C : private A { };
class D { };
static void
TestIsConvertible()
{
// Pointer type convertibility
MOZ_ASSERT((IsConvertible<A*, A*>::value),
"A* should convert to A*");
MOZ_ASSERT((IsConvertible<B*, A*>::value),
"B* should convert to A*");
MOZ_ASSERT((!IsConvertible<A*, B*>::value),
"A* shouldn't convert to B*");
MOZ_ASSERT((!IsConvertible<A*, C*>::value),
"A* shouldn't convert to C*");
MOZ_ASSERT((!IsConvertible<A*, D*>::value),
"A* shouldn't convert to unrelated D*");
MOZ_ASSERT((!IsConvertible<D*, A*>::value),
"D* shouldn't convert to unrelated A*");
// Instance type convertibility
MOZ_ASSERT((IsConvertible<A, A>::value),
"A is A");
MOZ_ASSERT((IsConvertible<B, A>::value),
"B converts to A");
MOZ_ASSERT((!IsConvertible<D, A>::value),
"D and A are unrelated");
MOZ_ASSERT((!IsConvertible<A, D>::value),
"A and D are unrelated");
// These cases seem to require C++11 support to properly implement them, so
// for now just disable them.
//MOZ_ASSERT((!IsConvertible<C*, A*>::value),
// "C* shouldn't convert to A* (private inheritance)");
//MOZ_ASSERT((!IsConvertible<C, A>::value),
// "C doesn't convert to A (private inheritance)");
}
int
main()
{
TestIsConvertible();
}