Boost logo

Boost :

Subject: Re: [boost] [optional] Changes in Boost.Optional
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2014-09-02 10:13:27


2014-09-02 15:39 GMT+02:00 Dean Michael Berris <mikhailberis_at_[hidden]>:

> On Tue Sep 02 2014 at 9:39:24 PM Andrzej Krzemienski <akrzemi1_at_[hidden]>
> wrote:
>
> > 2014-09-02 11:23 GMT+02:00 Dean Michael Berris <mikhailberis_at_[hidden]>:
> > > Right. My hunch is that 1.56 now has suppression for the cases where
> > > references would have been deduced (as discussed in
> > >
> > > http://www.boost.org/doc/libs/1_56_0/libs/optional/doc/html/
> > boost_optional/dependencies_and_portability/optional_
> > reference_binding.html
> > > ).
> > > Maybe the suppression applies even for the case when the conversion
> > > operator may have been useful for copy initialization.
> > >
> >
> > However, it works fine with GCC. It looks like VC++ compiler has a bug in
> > overload resolution in copy initialization. It should never consider
> > explicit constructors.
> >
> >
> Agreed that it works with GCC. I tested with Clang on OS X too and it
> doesn't display this problem.
>
> I think the specialization of the behavior for VC++ 2010 that came in
> 1.56.0 may be disabling the copy constructor inadvertently because the RHS
> resolves to a `const boost::optional<T>&` -- it may just be the case that
> the suppression to address the bug is too aggressive, and is causing a
> once-valid non-explicit constructor to be considered explicit? I can't be
> sure until I get to play around with it, or look deeply at the code to try
> and understand it.
>
> I won't be surprised if this is a compiler bug though. I would still like
> to know though whether there's a work-around, or whether I'm going to have
> to say in my upcoming release of cpp-netlib that we can't support Boost
> 1.56.0 with MSVC 2010. That announcement would be unfortunate. :(
>

Boost 1.56 has already been released, so we cannot fix your problem by
changing Boost sources. What you could try in your library is to detect if
you are compiling in VC++ and in that case not to cast to optional
directly, but to an auxiliary wrapper type:

#include <boost/optional.hpp>

struct container {
  boost::optional<int> optional() const {
    return value_;
  }
private:
  boost::optional<int> value_;
};

struct OptionalInt
{
  boost::optional<int> _o;
  explicit OptionalInt(boost::optional<int> o) :_o(o) {}
  operator boost::optional<int>() { return _o; }
};

struct value_wrapper {
  value_wrapper(const container& c) : c_(c) {}
  operator int () { return 1; }
  operator OptionalInt() { return OptionalInt(c_.optional()); }
private:
  const container& c_;
};

value_wrapper value(const container& c) {
  return value_wrapper(c);
}

int main()
{
  container c;
  // leave c.value_ alone.
  boost::optional<int> some_value =
    value(c);
  assert(!some_value);
}

This is not a correct C++, but it happens to work on VC++.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk