Boost logo

Boost :

Subject: [boost] [typeof] TYPEOF(this) on MSVC 7.1 and 8.0
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2012-01-14 16:37:11


Hello all,

BOOST_TYPEOF(this) generates error C2355 on MSVC 7.1 and 8.0 because
of a MSVC bug. The code below was suggested to workaround the problem
but it only works with native typeof.

Is there a way to make BOOST_TYPEOF(this) work on MSVC 7.1 and 8.0
with Boost.Typeof in emulation mode?

// Adam Butcher's workaround to deduce `this` type on MSVC revision < 10.
// Boost.Typeof for VC71's typeid-based workaround does not work to determine
// `this` type due to error C2355 being incorrectly reported. The typical
// avoidance strategy implemented below is to make an indirect compile-time
// constant by assigning an enum and use that as type-index-- this only works
// with the sizeof() approach and not with the typeid() approach. This does not
// work in typeof emulation mode.
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1300) && /* MSVC 7.1 */ \
        BOOST_WORKAROUND(BOOST_MSVC, <= 1400) && /* MSVC 8.0 */ \
        !defined(BOOST_TYPEOF_EMULATION) /* doesn't work in typeof-emu mode */

namespace boost { namespace scope_exit { namespace aux {
        namespace msvc_typeof_this {

template<int Id>
struct msvc_typeid_wrapper
{
    typedef typename boost::type_of::msvc_extract_type<boost::mpl::int_<Id>
>::id2type id2type;
    typedef typename id2type::type type;
};

template<>
struct msvc_typeid_wrapper<4>
{
    typedef msvc_typeid_wrapper<4> type;
};

template<typename T>
struct encode_type
{
    BOOST_STATIC_CONSTANT(unsigned,
            value = boost::type_of::encode_counter<T>::count);
    typedef typename boost::type_of::msvc_register_type<T,
            boost::mpl::int_<value> >::id2type type;
    BOOST_STATIC_CONSTANT(unsigned, next = value + 1);
};

template<class T>
struct sizer
{
    typedef char(*type)[encode_type<T>::value];
};

template<typename T>
typename boost::disable_if<
      typename boost::is_function<T>::type
    , typename sizer<T>::type
>::type encode_start(T const&);

template<typename T>
typename boost::enable_if<
      typename boost::is_function<T>::type
    , typename sizer<T>::type
>::type encode_start(T&);

template<typename Organizer, typename T>
boost::type_of::msvc_register_type<T, Organizer> typeof_register_type(const T&,
        Organizer* = 0);

} } } }

#define BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) \
    BOOST_PP_CAT(boost_se_thistype_index_, id)

#define BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, new_type) \
    enum { \
        BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) = sizeof( \
            *::boost::scope_exit::aux::msvc_typeof_this::encode_start(this)) \
    }; \
    typedef ::boost::scope_exit::aux::msvc_typeof_this::msvc_typeid_wrapper< \
            BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) \
>::type new_type;

#else // typeof(this) on other compilers are OK.

#define BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, new_type) \
    typedef BOOST_TYPEOF(this) new_type;

#endif // typeof(this)

For example:

// within a member function
BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(__LINE__, this_type);
this_type obj = this;

Thanks.
--Lorenzo


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk