Boost logo

Boost :

Subject: Re: [boost] [move] Implicit conversion to rvalues and move ctors.
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2014-08-28 03:07:11


Le 28/08/14 01:49, Mostafa a écrit :
> On Wed, 27 Aug 2014 16:17:06 -0700, Vicente J. Botet Escriba
> <vicente.botet_at_[hidden]> wrote:
>
>> Le 26/08/14 02:59, Mostafa a écrit :
>>> Here's another use case that fails to compile in C++03 but compiles
>>> successfully in C++11. (Note, it fails to compile in VS2005 and g++
>>> 4.8.2 -std=c++98, and compiles successfully with g++ 4.8.2 -std=c++11)
>>>
>>> MOC is a BOOST_MOVABLE_BUT_NOT_COPYABLE type. Foo is an empty with
>>> an implicit conversion function to MOC. "MOC m(Foo());" compiles
>>> successfully but "MOC m2(makeFoo());" fails to compile. Is this a
>>> bug or a limitation of Boost.Move in C++03?
>>>
>>> //----------
>>> //Start Code
>>> //----------
>>>
>>> #include <boost/move/core.hpp>
>>> #include <boost/move/utility.hpp>
>>>
>>> struct MOC
>>> {
>>> MOC() : value(121) {}
>>> MOC(BOOST_RV_REF(MOC) rhs) : value(rhs.value) {}
>>> int value;
>>> private:
>>> BOOST_MOVABLE_BUT_NOT_COPYABLE(MOC)
>>> };
>>>
>>> struct Foo
>>> {
>>> operator MOC ()
>>> {
>>> return MOC();
>>> }
>>> };
>>>
>>> Foo makeFoo()
>>> {
>>> return Foo();
>>> }
>>>
>>> int main()
>>> {
>>> // (1) Successfully Compiles.
>>> MOC m(Foo());
>>>
>>> // (2) Fails to Compile.
>>> MOC m2(makeFoo());
>>>
>>> return 0;
>>> }
>>>
>> I'm getting
>>
>> ../example/lambda_future.cpp:32:8: warning: parentheses were
>> disambiguated as a function declaration [-Wvexing-parse]
>> MOC m(Foo());
>> ^~~~~~~
>> ../example/lambda_future.cpp:32:9: note: add a pair of parentheses to
>> declare a variable
>> MOC m(Foo());
>> ^
>> ( )
>>
>>
>>
>> After adding the parentheses I get
>> ../example/lambda_future.cpp:32:7: error: no matching constructor for
>> initialization of 'MOC'
>> MOC m((Foo()));
>> ^ ~~~~~~~
>
> Yes, you're right. That would explain the different compiler behaviors
> between (1) and (2). Adding double parenthesis to both (1) and (2) now
> gives me the same error messages in g++ 4.8.2 -std=c++98. But they
> both do compile under C++11 mode. FWIW, I have an internal workaround,
> I'm just wondering if this is another undocumented limitation of
> Boost.Move in C++98.
>

There is something specific to conversions and move semantics that seems
to don't work. return an rvalue :(

#include <boost/move/core.hpp>
#include <boost/move/utility.hpp>

struct Bar
{};
struct MOC
{
   MOC() : value(121) {}
   MOC(Bar) : value(122) {}
   MOC(BOOST_RV_REF(MOC) rhs) : value(rhs.value) {}
   int value;
private:
   BOOST_MOVABLE_BUT_NOT_COPYABLE(MOC)
};

struct Foo
{
   operator MOC () const
   {
     return MOC();
   }
};

Foo makeFoo()
{
   return Foo();
}
Bar makeBar()
{
   return Bar();
}

MOC makeMOC()
{
   return MOC();
}

void f(MOC) {}
void g(MOC&) {}
void h(MOC const&) {}

int main()
{
   // (1) Fails to Compile..
   //MOC m(Foo());
   //MOC m((Foo()));
   // (1a) Compile.
   MOC m((Bar()));

   // (2) Fails to Compile.
   // MOC m2(makeFoo());
   // (2a) Compiles.
   MOC m3(makeMOC());
   MOC m4(makeBar());

   // (3) Compiles.
   f(MOC());
   // (3.a) Fails to Compile.
   //f(Bar());
   //f(Foo());

   // (4) Compiles.
   MOC x;
   g(x);
   // (4.a) Fails to Compile.
   //Bar y;
   //g(y);
   //Foo z;
   //g(z);

   // (5) Fails to Compile.
   //h(MOC()); // Normal is not MOC is not CopyConstructible
   // (5.a) Compiles.
   h(Bar()); // MOC is not Constructible from Bar
   h(Foo()); // // Foo is convertible to MOC

   return 0;
}
> (What's strange is that on my machine -Wall -pedantic doesn't even
> catch that MVPE you noted above.)
>
Here it is my cl

"/Users/viboes/clang/clang+llvm-3.2-x86_64-apple-darwin11/bin/clang++"
-x c++ -Wextra -Wno-long-long -Wunused-function -Wno-unused-value
-Wno-c99-extensions -Wno-variadic-macros -O0 -g -O0 -fno-inline -Wall -g
-DBOOST_ALL_NO_LIB=1 -DBOOST_CHRONO_STATIC_LINK=1
-DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_SYSTEM_STATIC_LINK=1
-DBOOST_THREAD_BUILD_LIB=1 -DBOOST_THREAD_POSIX
-DBOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
-DBOOST_THREAD_USE_LIB=1 -I"../../.." -c -o
"../../../bin.v2/libs/thread/test/ex_lambda_future2_lib.test/clang-darwin-3.2/debug/threading-multi/lambda_future.o"
"../example/lambda_future.cpp"

Vicente


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