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