2015-06-14 99 views
-1

對不起,這裏的noob問題,但我甚至不知道在谷歌上搜索什麼。我在移動語義上嘗試了一些文檔,但我仍然無法解決我的問題。C++ unordered_map移動初學者錯誤

所以如果有人能給我一些線索,我會非常感謝。

關於代碼:

graph.hpp:

#ifndef GRAPH_HPP 
#define GRAPH_HPP 

#include <cstdlib> 
#include <unordered_map> 
#include <vector> 
#include <string> 

template<typename T, typename U> 
class Link; 
template<typename T, typename U> 
class Node; 

namespace graph 
{ 
    template<typename T, typename U> 
    class Link 
    { 
     public: 
    Link() = default; 
    Link(U&& data, T& node) : _data(data), _endNode(node) {} 
    ~Link() = default; 

     private: 
    U   _data; 
    Node<T, U>& _endNode; 
    }; 

    template<typename T, typename U> 
    class Node 
    { 
     public: 
    Node() = default; 
    Node(T&& data) : _data(data) {}; 
    ~Node() = default; 

    private: 
     T      _data; 
     std::vector<Link<T, U>> _links; 
    }; 

    template<typename K, typename T, typename U> 
    class Graph 
    { 
     public: 
     Graph() = default; 
     ~Graph() = default; 

     private: 
     size_t        _nbNode; 
     std::unordered_map<K, Node<T, U>> _nodes; 

     public: 
     #include "graph.tpp" 
    }; 
} 
#endif 

graph.tpp:

void add_Link(const K& key1, 
      const K& key2, 
      U&& linkInfo) 
{ 
    if (!_nodes.count(key1) 
     || !_nodes.count(key2)) 
    throw "Key doesn't exist!"; 

    Link<T, U> newLink(linkInfo, _nodes[key2]); 
    _nodes[key1].links.push_back(newLink); 
} 

void add_Node(K& key, T&& elem) 
{ 
    Node<T, U> newNode(std::move(elem)); 
    _nodes[key] = std::move(newNode); 
} 

main.cpp中:

#include "graph.hpp" 
#include <string> 

int main() 
{ 
    std::string name("name"); 
    graph::Graph<std::string, std::string, std::string> graph; 

    graph.add_Node(name, "lol"); 
    return 0; 
} 

我只想補充unordered_map中的一個新元素採取行動。但它只是說我:

clang++ -Wall -Wextra -std=c++14 -O2 -march=native -s -fomit-frame-pointer -c src/test.cpp -o obj/test.o -I ./src/include -I ./src/template/ 
clang: warning: argument unused during compilation: '-s' 
In file included from src/test.cpp:1: 
In file included from ./src/include/graph.hpp:15: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/unordered_map:41: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/tuple:39: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/array:38: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/stdexcept:39: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/string:40: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/char_traits.h:39: 
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:336:18: error: object of type 'graph::Link<std::basic_string<char>, std::basic_string<char> >' cannot be assigned because its copy 
     assignment operator is implicitly deleted 
       *__result = *__first; 
         ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:396:36: note: in instantiation of function template specialization 'std::__copy_move<false, false, 
     std::random_access_iterator_tag>::__copy_m<const graph::Link<std::basic_string<char>, std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here 
           _Category>::__copy_m(__first, __last, __result); 
             ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:432:23: note: in instantiation of function template specialization 'std::__copy_move_a<false, const graph::Link<std::basic_string<char>, 
     std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here 
     return _OI(std::__copy_move_a<_IsMove>(std::__niter_base(__first), 
        ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:464:20: note: in instantiation of function template specialization 'std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<const 
     graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > > > >, 
     __gnu_cxx::__normal_iterator<graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, 
     std::basic_string<char> > > > > >' requested here 
     return (std::__copy_move_a2<__is_move_iterator<_II>::__value> 
       ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/vector.tcc:206:27: note: in instantiation of function template specialization 'std::copy<__gnu_cxx::__normal_iterator<const 
     graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > > > >, 
     __gnu_cxx::__normal_iterator<graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, 
     std::basic_string<char> > > > > >' requested here 
       std::_Destroy(std::copy(__x.begin(), __x.end(), begin()), 
           ^
./src/include/graph.hpp:40:10: note: in instantiation of member function 'std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > > 
     >::operator=' requested here 
    class Node 
     ^
src/test.cpp:9:9: note: in instantiation of member function 'graph::Graph<std::basic_string<char>, std::basic_string<char>, std::basic_string<char> >::add_Node' requested here 
    graph.add_Node(name, "lol"); 
     ^
./src/include/graph.hpp:36:15: note: copy assignment operator of 'Link<std::basic_string<char>, std::basic_string<char> >' is implicitly deleted because field '_endNode' is of reference type 
     'Node<std::basic_string<char>, std::basic_string<char> > &' 
     Node<T, U>& _endNode; 
        ^
In file included from src/test.cpp:1: 
In file included from ./src/include/graph.hpp:15: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/unordered_map:41: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/tuple:39: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/array:38: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/stdexcept:39: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/string:40: 
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/char_traits.h:39: 
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:336:18: error: object of type 'graph::Link<std::basic_string<char>, std::basic_string<char> >' cannot be assigned because its copy 
     assignment operator is implicitly deleted 
       *__result = *__first; 
         ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:396:36: note: in instantiation of function template specialization 'std::__copy_move<false, false, 
     std::random_access_iterator_tag>::__copy_m<graph::Link<std::basic_string<char>, std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here 
           _Category>::__copy_m(__first, __last, __result); 
             ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:432:23: note: in instantiation of function template specialization 'std::__copy_move_a<false, graph::Link<std::basic_string<char>, 
     std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here 
     return _OI(std::__copy_move_a<_IsMove>(std::__niter_base(__first), 
        ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:464:20: note: in instantiation of function template specialization 'std::__copy_move_a2<false, graph::Link<std::basic_string<char>, 
     std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here 
     return (std::__copy_move_a2<__is_move_iterator<_II>::__value> 
       ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/vector.tcc:211:13: note: in instantiation of function template specialization 'std::copy<graph::Link<std::basic_string<char>, std::basic_string<char> > 
     *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here 
       std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(), 
       ^
./src/include/graph.hpp:40:10: note: in instantiation of member function 'std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > > 
     >::operator=' requested here 
    class Node 
     ^
src/test.cpp:9:9: note: in instantiation of member function 'graph::Graph<std::basic_string<char>, std::basic_string<char>, std::basic_string<char> >::add_Node' requested here 
    graph.add_Node(name, "lol"); 
     ^
./src/include/graph.hpp:36:15: note: copy assignment operator of 'Link<std::basic_string<char>, std::basic_string<char> >' is implicitly deleted because field '_endNode' is of reference type 
     'Node<std::basic_string<char>, std::basic_string<char> > &' 
     Node<T, U>& _endNode; 
        ^
2 errors generated. 
Makefile:43: recipe for target 'obj/test.o' failed 
make: *** [obj/test.o] Error 1 

對不起,有一個愉快的一天。

回答

2

好的。問題出現在這一行:

_nodes[key] = std::move(newNode); 

您正在嘗試移動分配Node<T, U>。然而,Node不會有欠繳隱式聲明的舉動賦值運算符,因爲有一個用戶聲明的析構函數:

~Node() = default; 

其結果是,該行實際上是調用的Node<T, U>副本賦值操作符,它執行會員明智的副本。 Node<T, U>的成員之一是類型std::vector<Link<T, U>>,其中Link<T, U>有一個成員變量,它是一個引用。引用不是可複製分配的,所以複製賦值運算符被隱式刪除。因此,沒有找到拷貝分配操作符,所以該行是不合格的。

雖然引用不動,要麼分配,一個vector<Link<T,U>>是移動轉讓的,所以最簡單的解決方法就是刪除線,你聲明爲缺省的析構函數:

//~Node() = default; 

隨即,編譯器會隱式聲明默認的移動構造函數/賦值,並且此代碼將按照您的期望執行。並編譯。

側面說明,這是一個非常糟糕的主意:

public: 
    #include "graph.tpp" 
}; 
+0

謝謝您的回答。 我已經試過了,但之後的錯誤對我來說完全不可理解,我會更新主題。 – user3409642

+1

@ user3409642請提供[最小,完整和可驗證的示例](http://www.stackoverflow.com/help/mcve)。如果不知道任何類型是什麼,我不可能說出你的問題。 – Barry

+0

完成我想,如果你認爲它不夠簡單,請說我。 – user3409642