看看链表的这种实现方式:
#include <memory>
#include <type_traits>
#include <iostream>
using namespace std;
template<typename D>
class List {
struct Node {
shared_ptr<D> data;
Node* next;
Node(shared_ptr<D> d, Node* p, Node* n) : data(d), next(n) {}
~Node() {
data.reset();
delete next;
}
};
template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
typedef std::forward_iterator_tag iterator_category;
typedef shared_ptr<D> value_type;
typedef std::ptrdiff_t Distance;
typedef typename conditional<isconst, const value_type&, value_type&>::type
Reference;
typedef typename conditional<isconst, const value_type*, value_type*>::type
Pointer;
typedef typename conditional<isconst, const Node*, Node*>::type
nodeptr;
iterator(nodeptr x = nullptr) : curr_node(x) {}
iterator(const iterator<false>& i) : curr_node(i.curr_node) {}
Reference operator*() const { return curr_node->data; }
Pointer operator->() const { return &(curr_node->data); }
template<bool A>
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
return a.curr_node == b.curr_node;
}
template<bool A>
friend bool operator!=(const iterator<A>& a, const iterator<A>& b) {
return !(a.curr_node == b.curr_node);
}
friend class List<D>;
iterator& operator++() {
curr_node = curr_node->next;
return *this;
}
private:
nodeptr curr_node;
};
public:
List() {
head = nullptr;
}
int len() const {
int ret = 0;
for (const auto& n : *this) {
ret++;
}
return ret;
}
~List() {
delete head;
}
std::ostream& dump(std::ostream &strm) const {
for (const auto s : *this) {
strm << *s << std::endl;
}
return strm;
}
iterator<false> begin() {
return iterator<false>(head);
}
iterator<false> end() {
return iterator<false>(nullptr);
}
iterator<true> begin() const {
return iterator<true>(head);
}
iterator<true> end() const {
return iterator<true>(nullptr);
}
private:
Node* head;
};
给我带来麻烦的部分是此列表的iterator
实现。迭代器模板应该提供可变的和const
迭代器。
这是一个使用此实现的程序:
#include "List.h"
#include <iostream>
int main( int argc, const char *argv[] ) {
List<int> l;
std::cout << l.len() << std::endl;
return 0;
}
如果我使用clang++
,程序可以编译并运行良好,但是g++
的编译失败,并出现以下错误:
In file included from t.cpp:1:
List.h: In instantiation of ‘struct List<int>::iterator<false>’:
List.h:136:5: required from ‘int List<D>::len() const [with D = int]’
t.cpp:7:24: required from here
List.h:64:21: error: redefinition of ‘template<bool A> bool operator==(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
^~~~~~~~
List.h:64:21: note: ‘template<bool A> bool operator==(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’ previously declared here
List.h:69:21: error: redefinition of ‘template<bool A> bool operator!=(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’
friend bool operator!=(const iterator<A>& a, const iterator<A>& b) {
^~~~~~~~
List.h:69:21: note: ‘template<bool A> bool operator!=(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’ previously declared here
此错误的原因是什么?我怎样才能解决这个问题?
答案 0 :(得分:3)
问题似乎在这里:
function theScore (students) {
const highScoresByClass = {};
const scores = {A: 0, B: 0, C: 0};
for (const student of students){
const classHighScore = scores[student.class];
if(classHighScore < student.score) {
scores[student.class] = student.score;
highScoresByClass[student.class] = {
name: student.name,
score: student.score
};
};
};
return highScoresByClass;
};
console.log(theScore([
{
name: 'Sara',
score: 90,
class: 'A'
},
{
name: 'Poyi',
score: 85,
class: 'B'
},
{
name: 'Adert',
score: 74,
class: 'A'
},
{
name: 'Shynta',
score: 78,
class: 'B'
}
]));
这是说:对于template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
template<bool A>
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
return a.curr_node == b.curr_node;
}
(外部模板参数)的所有值,请定义模板函数isconst
。
因此实例化template<bool A> bool operator==
将定义iterator<true>
,然后实例化template<bool A> bool operator==
将再次定义iterator<false>
,从而导致重新定义错误。
解决方案:卸下内部模板。让template<bool A> bool operator==
的每个实例仅定义自己的iterator
:
operator==
(template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
friend bool operator==(const iterator& a, const iterator& b) {
return a.curr_node == b.curr_node;
}
会自动引用iterator
,即当前实例。)