On Apr 27, 2012, at 4:56 PM, Jeffrey Lee Hellrung, Jr. wrote:

On Fri, Apr 27, 2012 at 12:47 PM, Jonathan Jones <Jonathan.Jones@mathworks.com> wrote:
Hello,

The following code fails to compile when using GCC 4.4.6 and boost::optional from Boost 1.49:

Hmmm...seems to build fine for me with MSVC9 (also Boost 1.49.0)

The problem seems specific to GCC.  It compiles fine for me with MSVC 9 and clang 2.1.  I'm guessing this is in part due to the fact that with both those compilers, boost::is_convertible is implemented using compiler intrinsics, whereas this is not the case with GCC.

   #include <boost/optional/optional.hpp>
   #include <boost/type_traits/is_convertible.hpp>

   struct grill
   {
       template<typename U>
       grill (U)
       {}
   };

   template<typename T>
   struct bar
   {
       template<typename U>
       bar (U,
            typename boost::is_convertible<U,T>::type* = 0)
       {}
   };

   void foo()
   {
       typedef bar<grill> data_type;

       boost::optional<data_type> opt;
       boost::optional<data_type> opt2(opt); // this line
       (void)opt2;
   }


Here are the error messages (I apologize for the long lines, I shortened them as much as possible by truncating the header paths):


type_traits/is_convertible.hpp: In instantiation of ‘const bool boost::detail::is_convertible_basic_impl<boost::optional_detail::optional_base<bar<grill> >&, grill>::value’:
type_traits/is_convertible.hpp:329:   instantiated from ‘const bool boost::detail::is_convertible_impl<boost::optional_detail::optional_base<bar<grill> >, grill>::value’
type_traits/is_convertible.hpp:452:   instantiated from ‘boost::is_convertible<boost::optional_detail::optional_base<bar<grill> >, grill>’
optional/optional.hpp:604:   instantiated from ‘boost::optional<T>::optional(const boost::optional<T>&) [with T = bar<grill>]’
optional.cpp:25:   instantiated from here
optional/optional.hpp:285: error: ‘boost::optional_detail::optional_base<T>::optional_base(const boost::optional_detail::optional_base<T>&) [with T = bar<grill>]’ is protected
type_traits/is_convertible.hpp:170: error: within this context
type_traits/is_convertible.hpp:170: error:   initializing argument 1 of ‘grill::grill(U) [with U = boost::optional_detail::optional_base<bar<grill> >]’
optional/optional.hpp:308: error: ‘boost::optional_detail::optional_base<T>::~optional_base() [with T = bar<grill>]’ is protected
type_traits/is_convertible.hpp:170: error: within this context


This reproduction case is distilled from a real world example (not my code) where bar=boost::fusion::vector1 and grill=boost::function<void()>

The code compiles fine using the same compiler and Boost 1.44.

Any ideas on the root of the problem?

I can't figure it out from a quick glance through optional.hpp :( Can you investigate what has changed in optional.hpp between 1.44 and 1.49?

I suspect the "breaking" change is this one: https://svn.boost.org/trac/boost/changeset/67183

Note that on lines 560 and 594, a call to static_cast was added for copy construction and assignment.  If I remove the static_cast, things start to compile again, but there isn't enough info in the change set as to why the static_casts were added.