6

If Boost is compiled without C++11 support the boost::filesystem uses emulated scoped enumerators. If you then take this built Boost and use it in a project with C++11 support you end up with a missing symbol because the declaration of boost::filesystem::copy_file() has changed.

There is an easy fix for this:

# if __cplusplus >= 201103L
#   define NO_SCOPED_ENUMS
# endif
# ifdef NO_SCOPED_ENUMS
#   if BOOST_VERSION < 105000
#     ifndef BOOST_NO_SCOPED_ENUMS
#       define BOOST_NO_SCOPED_ENUMS
#       define REMOVE
#     endif
#   else
#     ifndef BOOST_NO_CXX11_SCOPED_ENUMS
#       define BOOST_NO_CXX11_SCOPED_ENUMS
#       define REMOVE
#     endif
#   endif
# endif
# include "boost/filesystem.hpp"
# if defined(NO_SCOPED_ENUMS) && defined(REMOVE)
#   undef REMOVE
#   if BOOST_VERSION < 105000
#     undef BOOST_NO_SCOPED_ENUMS
#   else
#     undef BOOST_NO_CXX11_SCOPED_ENUMS
#   endif
# endif

This preprocess bit defines either the BOOST_NO_SCOPED_ENUMS or BOOST_NO_CXX11_SCOPED_ENUMS depending on the Boost version, includes boost/filesystem and then removes it again if it wasn't defined before (to be safe)

Now the issue here is that the scoped enumerators are turned off when we are compiling for C++11:

# if __cplusplus >= 201103L
#   define NO_SCOPED_ENUMS
# endif

However, if Boost has actually been compiled with C++11 support this will break again because the declaration will be changed. It needs to be something like:

// BOOST_COMPILED_WITH_CXX11 doesn't exist
# if (__cplusplus >= 201103L) && !defined(BOOST_COMPILED_WITH_CXX11)
#   define NO_SCOPED_ENUMS
# endif

This is where my question comes in:

tl;dr - Can I determine if Boost was compiled with C++11 support?

The closest I've found is:

However you run the configure script, when it finishes you will find a new header -user.hpp- located in the <boost-root>/libs/config/ directory. Note that configure does not install this header into your boost include path by default. This header contains all the options generated by the configure script, plus a header-section that contains the user settable options from the default version of (located under /boost/config/).

Matt Clarkson
  • 14,106
  • 10
  • 57
  • 85
  • In the fix above I had to remove if BOOST_VERSION < 105000, I used boost 1.56 and gcc 4.8.4 (linux mint 17). – Ernie Mur Dec 21 '21 at 15:32

1 Answers1

2

You don't want to link a C++11 project with non-C++11 libraries. C++11 breaks binary compatibility and while things may work in most cases, it will bite you in the butt at some point.

See also do we need to recompile libraries with c++11?

Community
  • 1
  • 1
thelamb
  • 486
  • 3
  • 10
  • 1
    Ok, thanks. If I understand that link correctly, they want to use C++11 which will require `gcc-4.7`+. They already have binaries compiled with `4.2.1`. They will have to recompile the binaries regardless of using C++11 or not because they are changing between a major release of gcc (which the gcc developers regard as a change in the major or minor release numbers) – Matt Clarkson Sep 13 '13 at 14:58
  • I have to confess that I didn't read the link thoroughly, I should have :). In any case, compiling a project with gcc-4.7 with --stdc++11, and linking with a library compiled with gcc-4.7 without --std=c++11 is not a good idea. Consider also that some headers may have pre-processor #if's based on whether C++11 support is available or not. Those #if's will evaluate differently when compiling the C++11 project compared to the C++03 library. Which may or may not break compatibility. This goes as well for mixing release and debug builds. – thelamb Sep 13 '13 at 15:24
  • Don't worry, I agree with you - Just clarifying the link ;) – Matt Clarkson Sep 13 '13 at 15:33