Opened 6 years ago

Closed 6 years ago

#12179 closed Bugs (fixed)

Including boost/optional/optional_fwd.hpp without first including boost/config.hpp doesn't compile.

Reported by: c.d.glover@… Owned by: Fernando Cacciola
Milestone: Boost 1.62.0 Component: optional
Version: Boost 1.61.0 Severity: Problem
Keywords: Cc:

Description

This code does not compile;

#include <boost/optional/optional_fwd.hpp>

int main() {

return 0;

}

It seems this is because optional_fwd.hpp tries to only depend on boost/config/suffix.hpp, but this file itself depends on other config macros that need to be included first.

I have been able to workaround this issue by including boost/config.hpp before optional_fwd.hpp

Change History (5)

comment:1 by post@…, 6 years ago

Here's a slightly different problem, but with the same solution:

If optional/optional_fwd.hpp is included before any boost header that includes config.hpp (for example optional.hpp), there are multiple problems. Example:

#include "boost/optional/optional_fwd.hpp"
#include "boost/optional.hpp"

int main() {
    return 0;
}

The first problem is a build failure because of inconsistent defines:

  1. optional/optional_fwd.hpp includes config/suffix.hpp
  2. config/suffix.hpp uses an include guard to prevent multiple inclusions of itself
  3. config/suffix.hpp doesn't define int128_type and uint128_type because BOOST_HAS_INT128 is not defined
  4. another boost header includes config.hpp
  5. config.hpp includes config/compiler/gcc.hpp
  6. config/compiler/gcc.hpp defines BOOST_HAS_INT128
  7. config.hpp includes config/suffix.hpp, but the include guard prevents reevaluation of the file

Now, we have BOOST_HAS_INT128 defined, but boost::int128_type and boost::uint128_type are not. If we now try to compile something that includes type_traits/is_integral.hpp (which optional/optional.hpp indirectly does), we get to this code, which doesn't compile due to unknown types:

#ifdef BOOST_HAS_INT128
template<> struct is_integral<boost::int128_type> : public true_type{};
template<> struct is_integral<boost::uint128_type> : public true_type{};
#endif

The second class of problems are redefinition warnings. Here's an example (there are multiple defines that get redefined):

  1. optional/optional_fwd.hpp includes config/suffix.hpp
  2. config/suffix.hpp first sets BOOST_LIKELY to a no-op default
  3. another boost header includes config.hpp
  4. config.hpp includes config/compiler/gcc.hpp
  5. config/compiler/gcc.hpp redefines BOOST_LIKELY to work as intended -> redefinition warning

As a conclusion, optional/optional_fwd.hpp should include config.hpp instead of config/suffix.hpp Currently, optional/optional_fwd.hpp is the only file in boost that includes config/suffix.hpp directly (not through config.hpp), so it's probably not meant to be used this way.

(context: I'm using gcc 5.3.1 on Fedora 23)

comment:2 by post@…, 6 years ago

I posted a pull request with the (trivial) fix for this problem on Github: https://github.com/boostorg/optional/pull/19

comment:3 by Tony Lewis <tonyelewis@…>, 6 years ago

I think this is related to ticket:12142.

comment:4 by akrzemi1, 6 years ago

A related ticket #12142 will be fixed in 1.62.0 release. Hopefully this one will be fixed as well.

comment:5 by akrzemi1, 6 years ago

Milestone: To Be DeterminedBoost 1.62.0
Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.