Boost logo

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