I am creating a library component that uses universal forwarding. This works fine in most cases but I have encountered a case where our linux build (seeminingly) incorrectly uses a copy constructor instead of a move constructor.
I was able to reproduce this in godbolt on gcc 7.5 (same as our linux build platform) with a MVE:
#include <iostream>
using namespace std;
struct A
{
A(){}
A(const A&) = delete;
A(A&& other){ cout << "move A " << endl; }
};
template<class T>
struct B
{
template<class U = T>
B(U&& other)
: m_a(std::forward<U>(other))
{
cout << "forward T into B " << endl;
}
T m_a;
};
B<A> foo(A a)
{
return a;
//return std::move(a);
}
int main()
{
A a;
auto b = foo(std::move(a));
}
For clarity I added the non compilable version to illustrate the problem.
Now, as far as I know I can't use (N)RVO in this case so a move is not inherently wrong but I'd rather avoid writing return move(...); When compiling this with gcc 8.1 (or a relatively recent MSVC) it does use the move constructor without the move. So is this just a compiler problem or is there something I need to improve on my "B" struct to handle this case?