Opened 11 years ago

Closed 9 years ago

#6219 closed Bugs (fixed)

Apple macros break compile of has_binary_operator

Reported by: John Gee <j.gee@…> Owned by: Vladimir Prus
Milestone: To Be Determined Component: type_traits
Version: Boost 1.48.0 Severity: Problem
Keywords: Cc: j.gee@…

Description

Short version: the Apple defined macro for check() breaks the compile of some files in Boost 1.48.

Long version

I upgraded from Boost 1.44 to 1.48 and my compile broke. A little digging determined it is a conflict with the check() macro defined in AssertMacros.h which currently makes its way into many compiles. This problem has come up before, see https://svn.boost.org/trac/boost/ticket/2115.

I am compiling on Mac OS X Lion v10.7.2 with Apple LLVM compiler 3.0. This code is enough to show the problem:

#include <Carbon/Carbon.h> #include "boost/type_traits.hpp"

or more directly #include <AssertMacros.h> #include "boost/type_traits.hpp"

The first errors happen in this code in has_binary_operator.hpp where check is used.

template < typename Lhs, typename Rhs >
struct operator_exists {
   static ::boost::type_traits::yes_type check(has_operator); // this version is preferred when operator exists
   static ::boost::type_traits::no_type check(no_operator); // this version is used otherwise

   BOOST_STATIC_CONSTANT(bool, value = (sizeof(check(((make<Lhs>() BOOST_TT_TRAIT_OP make<Rhs>()),make<has_operator>())))==sizeof(::boost::type_traits::yes_type)));
};

Of some interest, Apple is aware of the problems being caused by the too-ordinary macro names and this text appears in the AssertMacros.h header:

*      Prior to Mac OS X 10.6 the macro names used in this file conflicted with some
 *      user code, including libraries in boost and the proposed C++ standards efforts,
 *      and there was no way for a client of this header to resolve this conflict. Because
 *      of this, most of the macros have been changed so that they are prefixed with 
 *      __ and contain at least one capital letter, which should alleviate the current
 *      and future conflicts.  However, to allow current sources to continue to compile,
 *      compatibility macros are defined at the end with the old names.  A tops script 
 *      at the end of this file will convert all of the old macro names used in a directory
 *      to the new names.  Clients are recommended to migrate over to these new macros as
 *      they update their sources because a future release of Mac OS X will remove the
 *      old macro definitions ( without the double-underscore prefix ).  Clients who
 *      want to compile without the old macro definitions can define the macro
 *      __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES to 0 before this file is
 *      included.

(So there is a work-around in client code.)

Change History (11)

comment:1 by John Gee <j.gee@…>, 11 years ago

(I regret not previewing the report, mea culpa for the cosmetic grinkles.)

comment:2 by John Gee <j.gee@…>, 11 years ago

Cc: j.gee@… added

comment:3 by Marshall Clow, 11 years ago

This definition __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0 should definitely go into the darwin tool config.

comment:4 by Marshall Clow, 11 years ago

Component: NoneBuilding Boost
Owner: set to Vladimir Prus

Should probably also go into the clang-darwin toolset as well.

Changing to "building boost", and assigning to Vladmir. If he's not the right person, I'm sure he'll chime in.

in reply to:  3 comment:5 by René Rivera, 11 years ago

Component: Building BoostRegression Testing

Replying to marshall:

This definition __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0 should definitely go into the darwin tool config.

Perhaps.. But that doesn't actually solve the problem. For users that do not use BB it would still break. As would also anyone compiling with an older OSX,or iOS, SDK. So we need to identify where the problems in the code are an file individual bugs. And as a preliminary step we should add this macro to the inspection report, if it's not already there. And because of that I'm shifting this to the testing side.

comment:6 by viboes, 10 years ago

Component: Regression Testingtype_traits

comment:7 by ben.craig@…, 9 years ago

Just ran into this with boost 1.55. This could be fixed without ever touching ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES. Just change the static variable names in operator_exists ( type_traits/detail/has_binary_operator.hpp ) from "check" to something else.

comment:8 by Marshall Clow, 9 years ago

Sadly, there is lots more than just this.

  • boost/container/detail/function_detector.hpp has a template member named "check"
  • Boost.Concept has structures named both "check" and "require"
  • Boost.Geometry has several uses of "check"

and the file <AssertMacros.h> defines many more macros than just those two.

comment:9 by ben.craig@…, 9 years ago

The perfect is the enemy of the good?

Fixing has_binary_operator.hpp fixes a lot of real use cases (lexical_cast for one) by just changing some internal identifiers. Even if you don't fix every use case, you make some use cases better, without making any use cases worse.

comment:10 by anonymous, 9 years ago

This took me almost two hours to sort out yesterday. Perhaps the addition of something like...

#if defined(__MACH__) && defined(__APPLE__) && defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) && __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES
#warning You will need to define ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES to 0 before the inclusion of Cocoa headers (perhaps in your prefix header) 
#end if

...might help lower the impedance here. Or something to that effect. While it may be non-trivial to work around this vendor annoyance, mankind does possess the technology to at least shorten the path to the workaround.

comment:11 by John Maddock, 9 years ago

Resolution: fixed
Status: newclosed

This is fixed in current develop (or at least type_traits is, can't comment on other libraries).

Note: See TracTickets for help on using tickets.