[Boost-bugs] [Boost C++ Libraries] #1916: [mpl] MPL_HAS_XXX_TRAIT_DEF bug in MSVC71

Subject: [Boost-bugs] [Boost C++ Libraries] #1916: [mpl] MPL_HAS_XXX_TRAIT_DEF bug in MSVC71
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2008-05-14 10:24:32


#1916: [mpl] MPL_HAS_XXX_TRAIT_DEF bug in MSVC71
---------------------------------------------------------+------------------
 Reporter: Adam Butcher <adam.butcher_at_[hidden]> | Owner: agurtovoy
     Type: Bugs | Status: new
Milestone: Boost 1.36.0 | Component: mpl
  Version: Boost 1.35.0 | Severity: Problem
 Keywords: mpl MPL_HAS_XXX_TRAIT_DEF msvc |
---------------------------------------------------------+------------------
 The MSVC71 implementation of MPL_HAS_XXX_TRAIT_DEF does not correctly
 support defining a trait of the same name even if that is enclosed within
 a different namespace. It seems to have something to do with the
 instantiation of the 'msvc71_sfinae_helper'. In the code below I do the
 following:
 {{{
 #!cpp
 namespace one
 {
    BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
    BOOST_MPL_HAS_XXX_TRAIT_DEF(another_type)
 }

 namespace two
 {
    BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
 }
 }}}
 Namespace two's {{{has_result_type}}} actually ends up testing for the
 presence of {{{another_type}}} rather than {{{result_type}}}. If the
 declarations in namespace one are reordered so that result_type trait is
 last, then the namespace two trait works as expected.

 I wrote a basic sfinae trait-check implementation myself which worked ok.
 Maybe something similar could be used for msvc71 in the mpl?

 If the following code is compiled with -DUSE_MPL_TRAIT_DEF then the mpl is
 used, otherwise my own implementation is used.

 {{{
 #!cpp

 #if USE_MPL_TRAIT_DEF

    #define SELECTIVE_HAS_XXX_TRAIT_DEF BOOST_MPL_HAS_XXX_TRAIT_DEF
    #include <boost/mpl/has_xxx.hpp>

 #else

    #define SELECTIVE_HAS_XXX_TRAIT_DEF MY_HAS_XXX_TRAIT_DEF
    #define MY_HAS_XXX_TRAIT_DEF( trait )
 \
       template <class T>
 \
       struct has_##trait
 \
       {
 \
          template <typename U>
 \
          static char test( U const volatile*, typename U::trait* = 0 );
 \
          static long test( ... );
 \
 \
          static const bool value = sizeof test( static_cast<T*>(0) ) ==
 sizeof(char); \
       };
 \

 #endif


 namespace one
 {
    SELECTIVE_HAS_XXX_TRAIT_DEF(result_type)
    SELECTIVE_HAS_XXX_TRAIT_DEF(another_type)
 }


 namespace two
 {
    // This instantiation of msvc71_sfinae_helper in the msvc71
    // implementation has been seen before --- but its function is that
    // of the last trait def.
    //
    // This line has the effect of defining a 'has_result_type' struct
    // that tests for 'another_type' in msvc71.
    //
    SELECTIVE_HAS_XXX_TRAIT_DEF(result_type)
 }


 template <bool> struct test;
 template <> struct test<true> {};


 struct X
 {
    typedef int result_type;
    typedef int another_type;
 };


 struct Y
 {
    typedef int result_type;
 };


 int main()
 {
    test< one::has_another_type< X >::value >();
    test< one::has_result_type< X >::value >();

    // this works but is actual testing for 'another_type'!!!
    test< two::has_result_type< X >::value >();

    // this fails as it doesn't have 'another_type'
    test< two::has_result_type< Y >::value >();
 }
 }}}

--
Ticket URL: <http://svn.boost.org/trac/boost/ticket/1916>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.


This archive was generated by hypermail 2.1.7 : 2017-02-16 18:49:57 UTC