|
Boost : |
From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-10-23 09:43:57
Peter Dimov wrote:
> is_incomplete can never work. It violates ODR. ;-)
You are right, of course. It should be something like this instead:
namespace {
template< typename T1, typename T2 >
struct is_incomplete_tag
{
};
} // namespace
template< typename T, int >
struct identity_if
{
typedef T type;
};
template< typename T >
struct identity_if<T,0>
{
};
template<
typename T
, typename Tag
, typename U_ = T
, typename tag_ = is_incomplete_tag<T,Tag>
>
struct is_incomplete
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template< typename T, typename Tag >
struct is_incomplete<
T
, Tag
, typename identity_if< T, sizeof(T) >::type
>
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
where 'is_incomplete_tag<>' guards you from ODR violations between different
translation units, and the second explicit template parameter allows you to
"tag" the points of different 'is_incomplete' instantiations within the
single translation unit:
// usage
template< typename T >
struct something
: mpl::if_c<
is_incomplete< T, something<T> >::value
, something_impl1<T>
, something_impl2<T>
>
{
};
Hmm, actually we can do even better:
#define BOOST_IS_INCOMPLETE(T) \
is_incomplete< T, boost::mpl::integral_c<long,__LINE__> > \
/**/
template< typename T >
struct something
: mpl::if_c<
BOOST_IS_INCOMPLETE(T)::value
, something_impl1<T>
, something_impl2<T>
>
{
};
Aleksey
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk