Opened 14 years ago
Last modified 10 years ago
#2262 new Bugs
BOOST_MPL_ASSERT_MSG producing linking problems in MSVC++ 8.0
Reported by: | Joaquín M López Muñoz | Owned by: | Aleksey Gurtovoy |
---|---|---|---|
Milestone: | Boost 1.37.0 | Component: | mpl |
Version: | Boost Development Trunk | Severity: | Problem |
Keywords: | Cc: | juanj.g_soria@… |
Description
Steps to reproduce the problem:
- Create a basic console project in Visual Studio 2005
- Include files foo1.cpp and foo2.cpp
- Build; the following error shows up at linking time:
>Linking... >foo2.obj : error LNK2005: "public: static struct boost::mpl::failed * * * * * * * * * * * * (__thiscall `bool __cdecl f<int>(void)'::`2' ::ALWAYS_TRUE::** * * * * * * * * * * __cdecl `bool __cdecl f<int> (void)'::`2'::ALWAYS_TRUE0::assert_arg(void))(int)" (?assert_arg@ALWAYS_TRUE0@?1???$f@H@@YA_NXZ@SAPAPAPAPAPAPAPAPAPAPAPAP8 ALWAYS_TRUE@?1???$f@H@@YA_NXZ@AEPAPAPAPAPAPAPAPAPAPAPAPAUfailed@mpl@boost@@H@ZXZ) already defined in foo1.obj
Attachments (2)
Change History (5)
by , 14 years ago
comment:1 by , 14 years ago
comment:2 by , 13 years ago
Cc: | added |
---|
Hi, Joaquin!
We have found this problem when recently converting a template parser from spirit classic to spirit 2.1.
I don't know why it's different when used outside a function, but the issue seems to reside in this fragment of boost/mpl/assert.hpp:
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) # define BOOST_MPL_ASSERT_MSG_IMPL( counter, c, msg, types_ ) \ struct msg; \ typedef struct BOOST_PP_CAT(msg,counter) : boost::mpl::assert_ \ { \ using boost::mpl::assert_::types; \ static boost::mpl::failed ************ (msg::************ assert_arg()) types_ \ { return 0; } \ } BOOST_PP_CAT(mpl_assert_arg,counter); \ BOOST_MPL_AUX_ASSERT_CONSTANT( \ std::size_t \ , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \ boost::mpl::assertion<(c)>::failed( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \ ) \ ) \ /**/ #else # define BOOST_MPL_ASSERT_MSG_IMPL( counter, c, msg, types_ ) \ struct msg; \ typedef struct BOOST_PP_CAT(msg,counter) : boost::mpl::assert_ \ { \ static boost::mpl::failed ************ (msg::************ assert_arg()) types_ \ { return 0; } \ } BOOST_PP_CAT(mpl_assert_arg,counter); \ BOOST_MPL_AUX_ASSERT_CONSTANT( \ std::size_t \ , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \ boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \ ) \ ) \ /**/ #endif
And actually in the { return 0; }
implementation of the functions, that actually produce non-local functions on MSVC 2005. These non-local functions then conflict at link time when the counter is the same.
I tried just leaving the those functions with no body (just the declarations), and then the problem went away, although Visual Studio would spit a lot of ugly warnings about a local class method with no implementation.
In the end I just removed the auxiliary auto-generated class and typedef, and just replaced the call to its member function with an expression that would yield the same type:
(boost::mpl::failed ************ (msg::************) types_) 0
This allowed me to remove the #ifdef
related to the MetroWerks compiler, since it was just changing the now removed structure.
I've tested this with Visual Studio 2005, and it works. I don't know if it will cause problems somewhere else. Perhaps there's some compiler out there that can't cast 0 to a pointer-to-member-function type...
by , 13 years ago
Attachment: | boost_assert_fix.diff added |
---|
Patch to assert.hpp, fixing BOOST_MPL_ASSERT_MSG link errors.
Additional comment: the duplicate symbol problem only happens when BOOST_MPL_ASSERT_MSG is used at function or member function level; at class level everything works OK.