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)

code.zip (574 bytes ) - added by Joaquín M López Muñoz 14 years ago.
boost_assert_fix.diff (1.7 KB ) - added by Juan Jesús García de Soria Lucena <juanj.g_soria@…> 13 years ago.
Patch to assert.hpp, fixing BOOST_MPL_ASSERT_MSG link errors.

Download all attachments as: .zip

Change History (5)

by Joaquín M López Muñoz, 14 years ago

Attachment: code.zip added

comment:1 by Joaquín M López Muñoz, 14 years ago

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.

comment:2 by Juan Jesús García de Soria Lucena <juanj.g_soria@…>, 13 years ago

Cc: juanj.g_soria@… 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 Juan Jesús García de Soria Lucena <juanj.g_soria@…>, 13 years ago

Attachment: boost_assert_fix.diff added

Patch to assert.hpp, fixing BOOST_MPL_ASSERT_MSG link errors.

comment:3 by hustzhanglin@…, 10 years ago

how to solve the error:"c" Undeclared identifier..

Note: See TracTickets for help on using tickets.