5

I have some code:

Class A{
//...A has a move ctor here.
};

unordered_map<int, A> bla;
A tmp;
//operations on tmp
bla.insert(make_pair<int, A>(1, move(tmp)));

I wanna call move constructor instead of copy ctor of class A. Is this code correct? I think so. The weird thing is it compiles and works for Ubuntu Precise (g++ show version of 4.6.3). But on CentOS, it failed to compile. The first few lines are:

 In substitution of ‘template<class _From1, class _To1> static decltype     ((__test_aux<_To1>(declval<_From1>()), std::__sfinae_types::__one()))     std::__is_convertible_helper<_From, _To, false>::__test(int) [with _From1 = _From1; _To1 = _To1; _From = const A&; _To = A] [with _From1 = const A&; _To1 = A]’:
/gcc/x86_64-redhat-linux/4.7.1/../../../../include/c++/4.7.1/type_traits:1258:70:   required from ‘constexpr const bool std::__is_convertible_helper<const A&, A, false>::value’
/gcc/x86_64-redhat-linux/4.7.1/../../../../include/c++/4.7.1/type_traits:1263:12:   required from ‘struct std::is_convertible<const A&, A>’
/gcc/x86_64-redhat-linux/4.7.1/../../../../include/c++/4.7.1/type_traits:116:12:   required from ‘struct std::__and_<std::is_convertible<const int&, int>, std::is_convertible<const A&, A> >’
/gcc/x86_64-redhat-linux/4.7.1/../../../../include/c++/4.7.1/bits/stl_pair.h:113:38:   required from ‘constexpr std::pair<typename std::__decay_and_strip<_T1>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = A; typename std::__decay_and_strip<_T2>::__type = A; typename std::__decay_and_strip<_T1>::__type = int]’

It seems trying to call copy ctor. Any ideas on this error?

Well, my CentOS does not have recent version of gcc/libstdc++, so actually i build these(gcc 4.7.1) by myself and install them in my home dir. Does this matter? This is my configuration when compiling:

Target: x86_64-redhat-linux
Configured with: ../gcc-4.7.1/configure --prefix=/home/bla/usr/ --with-mpc=/home/bla/usr/ --with-mpfr=/home/bla/usr/ --with-gmp=/home/bla/usr/ --disable-multilib --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++ --enable-java-awt=gtk --disable-dssi --disable-plugin --with-cpu=generic --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.7.1 (GCC)

UPDATE: Maybe there is sth wrong with the usage of "move semantic". I tried "move" with STL string:

unordered_map<int, string> bla;
string tmp("hello world");
//operations on tmp
bla.emplace(1, move(tmp));

It is just ok and the internal chars are really "moved".

But it does NOT work with my class A... This is A:

class A
{
    public:
        A(){...}
        ~A(){}
        A(A&& other){...}
    private:
        A& operator = (const A& other);
        A& operator = ( A&& other);
        A(const A& other);
};

UPDATE: i got it work, when A is:

class A
{
    public:
        A(){...}
        ~A(){}
        A(A&& other){...}
        A(const A& other){}
    private:
        A& operator = (const A& other);
        A& operator = ( A&& other);
};

Pay attention to the COPY CTOR. Now all my move semantic works correct and copy ctor is not actually called when running. Do i get sth wrong about "move"?

xgwang
  • 614
  • 7
  • 21
  • Tested with g++ 4.7.1 on Arch Linux and worked fine. – rodrigo Jul 17 '12 at 12:43
  • 6
    Actually you should use `.emplace` if the libstdc++ version is new enough. `bla.emplace(1, std::move(tmp))`. – kennytm Jul 17 '12 at 14:13
  • @AlexFarber well, i think so. It seems that gcc does not recognize the "move semantics". gcc -v shows the correct version, i will keep tracking it. – xgwang Jul 17 '12 at 15:11
  • @KennyTM thanks. i will try it later. As far as i remember, emplace was not implemented until recently? – xgwang Jul 17 '12 at 15:13
  • Variadic templates and rvalue references came with GCC 4.3. So `emplace` should be present in GCC 4.6.3. – Morwenn Jul 17 '12 at 15:15

2 Answers2

7

Don't specify the template arguments for std::make_pair, as that defeats its perfect-forwarding mechanisms. I.e., if you can't use emplace, then simply call make_pair as follows:

bla.insert(make_pair(1, move(tmp)));
ildjarn
  • 62,044
  • 9
  • 127
  • 211
-1

I believe that this question has the same answer as this question and could be a duplicated question.

However, i still have not successfully compile it when using noexcept keyword with move contstructor.

Community
  • 1
  • 1
xgwang
  • 614
  • 7
  • 21