2017-04-08 31 views
1

我在弄清楚为什么我无法得到std :: vector :: erase使用我自己的类对象的矢量时遇到了一些麻烦。下面的代码抛出一个“没有可行的重载‘=’”错误,并不能找出为什么一些广泛的溢出搜索/ tutorialspoint后/ ...当使用vector :: erase时,没有可行'='

我的类定义“MyClass.hpp”:

#include <string> 
#include <vector> 
class node; 
class graph{ 
public: 
    graph(); 
    std::vector<node> nodeList; 
}; 

class node{ 
public: 
    node(std::string name) : name(name){}; 
    void operator=(node& rhs); 
    std::string name; 
    std::vector<node> adjacent; 
}; 

void node::operator=(node& rhs){ 
    name = rhs.name; 
    adjacent = rhs.adjacent; 
} 

和我的主文件:

#include "MyClass.hpp" 
int main(int argc, const char * argv[]) { 
    node node1("root"), node2("leaf"); 
    node1.adjacent.push_back(node2); 
    node2.adjacent.push_back(node1); 
    node1.adjacent.erase(node1.adjacent.begin()); 
    graph myGraph; 
    return 0; 
} 
+0

这是完全可能的载体实现不具有不完全类型的新的支持(具有节点的载体的节点)。 – chris

+1

你的'operator ='坏了。赋值运算符必须采取'const'参考作为参数,并返回一个可变的参考,即,它应该是'节点&节点::运算符=(const的节点&RHS)',并返回'* this'。 –

+2

为什么你甚至自己定义'operator ='?编译器生成的会更好。见规则零。 – aschepler

回答

5

std::vector::erase补充说,向量的元素T类型必须是move assignable的要求。这尤其意味着像t = rv这样的表达式必须具有返回类型T &(参考T)和值t(因此返回的引用必须引用分配的对象)。

您的Node::operator=返回类型void,从而违反上述要求。此外,通常的(也可能是最合理的),键入复制/移动赋值运算符的签名如下:

T & operator=(T &&); // move assignment 
T & operator=(T); // copy assignment, pass by value 
T & operator=(T const &); // copy assignment, pass by const reference 

但是,而不是固定网络运营商,你应该放弃它一起!你Node类不(应该)处理所有权(该std::vector是这样做的你),因此每rule of zero你不应该提供自定义复制或移动赋值运算符(也没有析构函数)。

+0

根据[cppreference](http://en.cppreference.com/w/cpp/language/copy_assignment),OP的赋值运算符是一个复制赋值运算符。 – chris

+0

@chris我在标准中读过,事实上,复制赋值运算符的类型签名的唯一要求是'T','T&','T const&','T volatile& '或'T const volatile&'。 –

+0

同意。如果没有额外的逻辑来处理转换,那么分配必须是相同的T.然而,内置的C++集合中的边界案例的解决方案,但它们不应该总是依赖。 – James

相关问题