I'm not sure what's going on here, but with a recent 4.5 snapshot this program
fails:
#include <utility>
#include <cassert>
template<typename T>
struct S
{
S() : buf() { }
void set(T&& i) { buf = std::move(i); }
T&& get() { return std::move(buf); }
private:
T buf;
};
struct pod { };
template class S<int>;
template class S<double>;
template class S<pod>;
int main()
{
S<int> s;
s.set(5);
assert( s.get() == 5 );
}
Compiling with 4.5.0 20090528 gives these warnings:
tmpret.cc: In member function T&& S<T>::get() [with T = int]:
tmpret.cc:19: instantiated from here
tmpret.cc:11: warning: returning reference to temporary
tmpret.cc: In member function T&& S<T>::get() [with T = double]:
tmpret.cc:20: instantiated from here
tmpret.cc:11: warning: returning reference to temporary
tmpret.cc: In function int main():
tmpret.cc:27: warning: <anonymous> is used uninitialized in this function
And the assertion fails at runtime.
Notice that the explicit instantiations of S<int> and S<double> trigger the
warning about returning a reference to a temporary for this line:
T&& get() { return std::move(buf); }
but the S<pod> instantiation doesn't. I can't see what's wrong with that line,
it seems that std::move creates a temporary when 'T' is a builtin type.
It looks as though std::move(buf) instantiates std::move<T>(T&&) with T = int&,
so the rvalue-reference binds to an int& not an int.
Am I missing something or is this a bug in either std::move or g++?
N.B. the changes to std::move proposed by n2844 are not in the WP yet, so the
specification of std::move may change.
--
Summary: [C++0x] std::move and builtin types
Product: gcc
Version: 4.5.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: jwakely dot gcc at gmail dot com
GCC build triplet: x86_64-unknown-linux-gnu
GCC host triplet: x86_64-unknown-linux-gnu
GCC target triplet: x86_64-unknown-linux-gnu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40295