Boost logo

Boost Users :

Subject: Re: [Boost-users] Boost.Variant broke in 1.54?
From: Antony Polukhin (antoshkka_at_[hidden])
Date: 2013-08-09 03:33:39


2013/8/4 gast128 <gast128_at_[hidden]>

> Dear all,
>
> I get a compilation error with Boost.Variant (which compiles fine on
> previous releases) with vstudio 2010 when a function returns a const
> Boost.Variant, e.g.:
>
> typedef boost::variant<int, double> Variant;
>
> const Variant GetVar()
> {
> return Variant();
> }
>
>
> void TestVariantDnc()
> {
> const Variant var = GetVar();
> }
>
> This gives error C2666 ('boost::variant<T0_,T1>::convert_construct' : 3
> overloads have similar conversions').
>
> Shall a file a ticket or do I something wrong?
>

Let me explain why this is not a good C++11 code any more.
Take a look at the following code:

const some_type GetVar()
{
  return some_type();
}

Compiler instead of that will generate the following:

const some_type&& GetVar()
{
  return some_type();
}

So now, when you'll try to do something like this

const some_type var = GetVar();

Compiler will convert that to the following:

const some_type var(GetVar());

Because usually there are no constructors for const rvalues, compiler will
use the copy constructor for some_type (`some_type(const some_type&)`).

So, adding a const disables all the move constructors and rvalue
optimizations.

However that does not mean that Boost.Variant can fail with that error. To
fix that error you can use the following trick:

* Find the line that has enable_if<boost::is_rvalue_reference<
* Fix add to the enable_if condition check that type is not const

Here is an example, how to do it (this must fix compilation of your code):
Old version:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
    template <class T>
    variant(T&& operand, typename
boost::enable_if<boost::is_rvalue_reference<T&&> >::type* = 0)
    {
        convert_construct( detail::variant::move(operand), 1L);
    }
#endif

Fixed version:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
    template <class T>
    variant(T&& operand, typename
boost::enable_if_c<boost::is_rvalue_reference<T&&>::value &&
!boost::is_const<T>::value >::type* = 0)
    {
        convert_construct( detail::variant::move(operand), 1L);
    }
#endif

I've created ticket for that issue
https://svn.boost.org/trac/boost/ticket/8988. I'll take care of it as soon
as possible.

-- 
Best regards,
Antony Polukhin


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net