|
Boost : |
From: Eric Friedman (ebf_at_[hidden])
Date: 2003-10-31 20:26:45
To all-
Seeking to extend support of the variant< type-sequence > syntax to all
platforms, I've returned to the problem of simulating overload
resolution rules.
In this direction, I have implemented the following type trait, which
works as follows:
is_better_conversion< From, To1, To2 >
--> true iff conversion unambiguously prefers To1 over To2
I have previously determined that is_better_conversion is sufficient to
implement the variant< type-sequence > syntax. Unfortunately, I cannot
get it to compile on MSVC6 or Borland.
If anyone could help me in this regard (see attached files), it would be
of great benefit to users of Boost.Variant.
Thanks,
Eric
//-----------------------------------------------------------------------------
// boost type_traits/is_better_conversion.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_TYPE_TRAITS_IS_BETTER_CONVERSION_HPP
#define BOOST_TYPE_TRAITS_IS_BETTER_CONVERSION_HPP
#include "boost/detail/workaround.hpp"
#include "boost/type_traits/config.hpp"
#include "boost/type_traits/detail/yes_no_type.hpp"
#include "boost/mpl/and.hpp"
#include "boost/mpl/bool.hpp"
#include "boost/mpl/not.hpp"
namespace boost {
namespace detail {
#if !BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3))
template <typename From, typename To1, typename To2>
struct is_better_conversion_impl
{
private:
// Alexander Nasonov suggested (comp.lang.c++.moderated, 4 Jul 2002)
// the following fix for the ambiguous conversion case:
template <typename Int>
static ::boost::type_traits::no_type BOOST_TT_DECL check_(To2, Int);
static ::boost::type_traits::no_type BOOST_TT_DECL check_(...);
static ::boost::type_traits::yes_type BOOST_TT_DECL check_(To1, int);
static From from_;
public:
typedef ::boost::mpl::bool_<
( sizeof( check_(from_,0) ) == sizeof( ::boost::type_traits::yes_type ) )
> type;
void foo(); // avoid warning about all members being private
};
#else// g++ workaround
struct is_better_conversion_any_t
{
template <typename T> is_better_conversion_any_t(const T&);
template <typename T> is_better_conversion_any_t(T&);
};
template <typename To1, typename To2> struct is_better_conversion_checker
{
template <typename Int>
static boost::type_traits::no_type _m_check(To2, Int);
static boost::type_traits::no_type _m_check(is_better_conversion_any_t, ...);
static boost::type_traits::yes_type _m_check(To1, int);
};
template <typename From, typename To1, typename To2>
struct is_better_conversion_impl
{
static From _m_from;
static bool const value =
sizeof( is_better_conversion_checker<To1,To2>::_m_check(_m_from, 0) )
== sizeof(::boost::type_traits::yes_type);
typedef ::boost::mpl::bool_<value> type;
};
#endif // g++ workaround
} // namespace detail
template <typename From, typename To1, typename To2>
struct is_ambiguous_conversion
: mpl::and_< // is_better_impl< 1,2 > && is_better_impl< 2,1 >
detail::is_better_conversion_impl< From, To1,To2 >
, detail::is_better_conversion_impl< From, To2,To1 >
>
{
};
template <typename From, typename To1, typename To2>
struct is_better_conversion
: mpl::and_< // is_better_impl< 1,2 > && !is_ambiguous< 1,2 >
detail::is_better_conversion_impl< From, To1,To2 >
, mpl::not_< detail::is_better_conversion_impl< From, To2,To1 > >
>
{
};
} // namespace boost
#endif // BOOST_TYPE_TRAITS_IS_BETTER_CONVERSION_HPP
#include "boost/type_traits/is_better_conversion.hpp"
#include "boost/static_assert.hpp"
/////
#define TEST( from, to1, to2 ) \
BOOST_STATIC_ASSERT(( \
boost::is_better_conversion< from , to1 , to2 >::value \
)) \
/**/
#define TEST_AMBIGUOUS( from, to1, to2 ) \
BOOST_STATIC_ASSERT(( \
boost::is_ambiguous_conversion< from , to1 , to2 >::value \
)) \
/**/
/////
template <typename T>
struct is_constructible_from
{
is_constructible_from(const T&);
};
struct is_constructible_from_any
{
template <typename T>
is_constructible_from_any(const T&);
};
struct udt
{
};
/////
int main()
{
// TEST( from, better, worse )
TEST( udt, udt, is_constructible_from<udt> );
TEST( udt, udt, is_constructible_from_any );
TEST( float, double, char );
TEST( float, double, int );
// Ambiguous
TEST_AMBIGUOUS( udt, is_constructible_from<udt>, is_constructible_from_any );
TEST_AMBIGUOUS( double, int, int );
TEST_AMBIGUOUS( double, float, int );
TEST_AMBIGUOUS( int, long, double );
return 0;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk