我一直在进行小规模的测试,看看我是否可以用更大的容器找出一些特定于编译器的大规模问题。以下代码在GCC中正常工作但在Visual Studio 2010和2013中导致以下错误代码:
“错误1错误C2675:一元' - ':'std :: iterator'未定义此运算符或转换为预定义运算符可接受的类型d:\ programming \ workspaces \ adl_test \ main.cpp 127 1 adL_test_msvc“
测试代码如下:
#include <iostream>
#include <iterator>
namespace nsp
{
template <class element_type, class element_allocator_type = std::allocator<element_type> >
class test_container
{
private:
element_type numbers[50];
friend class iterator;
friend class reverse_iterator;
public:
class reverse_iterator; //forward decl
class iterator : public std::iterator<std::bidirectional_iterator_tag, element_type>
{
private:
element_type *i;
template <class distance_type>
friend void advance(reverse_iterator &rit, distance_type n);
public:
iterator() {}
iterator(element_type &_i)
{
i = &(_i);
}
element_type & operator *()
{
return *i;
}
iterator & operator = (const element_type &source_i)
{
i = &(source_i);
return *this;
}
iterator & operator = (const iterator &source)
{
i = source.i;
return *this;
}
bool operator != (const iterator rh)
{
return i != rh.i;
}
iterator & operator ++()
{
++i;
return *this;
}
iterator & operator --()
{
--i;
return *this;
}
template <class distance_type>
friend void advance(iterator &it, distance_type n)
{
it.i += n;
}
friend typename std::iterator_traits<iterator>::difference_type distance(const iterator &first, const iterator &last)
{
return last.i - first.i;
}
};
class reverse_iterator : public std::iterator<std::bidirectional_iterator_tag, element_type>
{
private:
iterator it;
public:
reverse_iterator(element_type &_i)
{
it.i = _i;
}
reverse_iterator(const iterator &source)
{
it = source;
}
element_type & operator *()
{
return *it;
}
element_type & operator = (const reverse_iterator &source)
{
it = source.it;
return *this;
}
element_type & operator = (const iterator &source)
{
it = source;
return *this;
}
bool operator != (const iterator rh)
{
return it != rh.it;
}
reverse_iterator & operator ++()
{
--it;
return *this;
}
reverse_iterator & operator --()
{
++it;
return *this;
}
template <class distance_type>
friend void advance(reverse_iterator &rit, distance_type n)
{
rit.it.i -= n;
}
friend typename std::iterator_traits<reverse_iterator>::difference_type distance(const reverse_iterator &first, const reverse_iterator &last)
{
return distance(last.it, first.it);
}
};
iterator begin()
{
return iterator(numbers[0]);
}
iterator end()
{
return iterator(numbers[50]);
}
};
}
int main(int argc, char **argv)
{
nsp::test_container<int> stuff;
int counter = 0;
for (nsp::test_container<int>::iterator it = stuff.begin(); it != stuff.end(); ++it)
{
*it = counter++;
}
nsp::test_container<int>::iterator it = stuff.begin(), it2 = stuff.begin();
using namespace std;
std::cout << *it << std::endl;
++it;
--it;
++it;
std::cout << *it << std::endl;
advance(it, 2);
std::cout << *it << std::endl;
std::advance(it, 2);
std::cout << *it << std::endl;
int distance_between = distance(it2, it);
std::cout << distance_between << std::endl;
nsp::test_container<int>::reverse_iterator rit = it, rit2 = it2;
--rit;
++rit;
advance(rit, -2);
distance_between = distance(rit2, rit);
std::cout << distance_between << std::endl;
std::cin.get();
return 0;
}
显然, - 运算符在迭代器上工作正常,如代码所示,但是当从reverse_iterator调用时,MSVC会产生错误,尽管reverse_iterator是朋友。为什么? 这个bug的解决方法是什么?
不建议使用不同的方式来接近代码(即直接修改i而不是调用 - 运算符),这是测试用例,而不是实际的工作代码。它并不代表实际代码的复杂性,我不会向您解释为什么实际代码以这种方式工作,因为我没有时间。
答案 0 :(得分:0)
感谢immibus,我们找到了答案: GCC相信&#39; iterator&#39;在reverse_iterator中引用test_container :: iterator,而(由于某种原因)MSVC 2010-2013认为它引用了基类。 在reverse_iterator中指定迭代器时,解决方案更具体 - 使用&#34; typename test_container :: iterator&#34;而不是&#34;迭代器&#34;。
更正后的代码:
#include <iostream>
#include <iterator>
namespace nsp
{
template <class element_type, class element_allocator_type = std::allocator<element_type> >
class test_container
{
private:
element_type numbers[50];
friend class iterator;
friend class reverse_iterator;
public:
class reverse_iterator; //forward decl
class iterator : public std::iterator<std::bidirectional_iterator_tag, element_type>
{
private:
element_type *i;
template <class distance_type>
friend void advance(reverse_iterator &rit, distance_type n);
public:
iterator() {}
iterator(element_type &_i)
{
i = &(_i);
}
element_type & operator *()
{
return *i;
}
iterator & operator = (const element_type &source_i)
{
i = &(source_i);
return *this;
}
iterator & operator = (const iterator &source)
{
i = source.i;
return *this;
}
bool operator != (const iterator rh)
{
return i != rh.i;
}
iterator & operator ++()
{
++i;
return *this;
}
iterator & operator --()
{
--i;
return *this;
}
template <class distance_type>
friend void advance(iterator &it, distance_type n)
{
it.i += n;
}
friend typename std::iterator_traits<iterator>::difference_type distance(const iterator &first, const iterator &last)
{
return last.i - first.i;
}
};
class reverse_iterator : public std::iterator<std::bidirectional_iterator_tag, element_type>
{
private:
typename test_container::iterator it;
public:
reverse_iterator(element_type &_i)
{
it.i = _i;
}
reverse_iterator(const typename test_container::iterator &source)
{
it = source;
}
element_type & operator *()
{
return *it;
}
element_type & operator = (const reverse_iterator &source)
{
it = source.it;
return *this;
}
element_type & operator = (const typename test_container::iterator &source)
{
it = source;
return *this;
}
bool operator != (const typename test_container::iterator rh)
{
return it != rh.it;
}
reverse_iterator & operator ++()
{
--it;
return *this;
}
reverse_iterator & operator --()
{
++it;
return *this;
}
template <class distance_type>
friend void advance(reverse_iterator &rit, distance_type n)
{
rit.it.i -= n;
}
friend typename std::iterator_traits<reverse_iterator>::difference_type distance(const reverse_iterator &first, const reverse_iterator &last)
{
return distance(last.it, first.it);
}
};
iterator begin()
{
return iterator(numbers[0]);
}
iterator end()
{
return iterator(numbers[50]);
}
};
}
int main(int argc, char **argv)
{
nsp::test_container<int> stuff;
int counter = 0;
for (nsp::test_container<int>::iterator it = stuff.begin(); it != stuff.end(); ++it)
{
*it = counter++;
}
nsp::test_container<int>::iterator it = stuff.begin(), it2 = stuff.begin();
using namespace std;
std::cout << *it << std::endl;
++it;
--it;
++it;
std::cout << *it << std::endl;
advance(it, 2);
std::cout << *it << std::endl;
std::advance(it, 2);
std::cout << *it << std::endl;
int distance_between = distance(it2, it);
std::cout << distance_between << std::endl;
nsp::test_container<int>::reverse_iterator rit = it, rit2 = it2;
--rit;
++rit;
advance(rit, -2);
distance_between = distance(rit2, rit);
std::cout << distance_between << std::endl;
std::cin.get();
return 0;
}