const迭代器的模板形参,而不是迭代器
template parameter for const iterator instead of iterator
注 :我根据从练习中得到的教训和答案写了一个"配方" & &;关于本页的评论,请参阅http://www.codeproject.com/Tips/1029941/Python-like-enumeration-in-Cplusplus。
我正在摆弄c++ 11给c++ 03带来的扩展。我希望能够使用以下代码迭代容器:
int main()
{
std::list<int> list = { 1, 2, 3, 4, 5, 6, 7 };
for (auto x : enumerated(list))
cout << x.first << " " << x.second << endl;
for (auto x : const_enumerated(list))
cout << x.first << " " << x.second << endl;
}
第一次迭代的x是可修改的,而对于第二次迭代,试图修改x将导致编译错误。我有一些适用于非const情况的东西:
template <typename Container>
class EnumerationAdaptor
{
public:
EnumerationAdaptor(Container& container) : container_(container) {}
EnumIter<typename Container::iterator> begin() const { return container_.begin(); }
EnumIter<typename Container::iterator> end() const { return container_.end(); }
private:
Container& container_;
};
template <typename Container>
EnumerationAdaptor<Container> enumerated(Container& container) { return container; }
template <typename Container>
EnumerationAdaptor<const Container> const_enumerated(const Container& container) { return container; }
非const情况使用EnumIter<std::list<...>::iterator>
,根据需要,我试图使const情况使用EnumIter<std::list<...>::const_iterator>
作为begin()
和end()
的返回类型。似乎我需要decltype:
template <typename Container>
class EnumerationAdaptor
{
public:
EnumerationAdaptor(Container& container) : container_(container) {}
EnumIter<decltype(Container().begin())> begin() const { return container_.begin(); }
EnumIter<decltype(Container().end())> end() const { return container_.end(); } // *** compile error (see below)
private:
Container& container_;
};
但我得到一个编译错误在Visual Studio 2015 Express:
Error C2440 'return': cannot convert from
'std::_List_const_iterator<std::_List_val<std::_List_simple_types<int>>>'
to
'EnumIter<std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>>'
[in c:users...enumeratedcpp.cpp line 46, which is line marked ***]
,这表明我做了一些错误的decltype,因为编译器正在寻找非const begin()。有办法解决这个问题吗?
EDIT:即使使用简单的EnumIter,问题也是一样的:
template <typename Iter>
class EnumIter
{
public:
EnumIter(Iter begin) : iter_(begin) {}
EnumIter& operator++()
{
return *this;
}
bool operator!=(const EnumIter& rhs)
{
return iter_ != rhs.iter_; // or self.index_ != rhs.index_;
}
int operator*() const
{
return index_;
}
private:
Iter iter_;
int index_ = 0;
};
这个表达式有一个问题:
decltype(Container().begin())
即Container()
仅在Container
恰好是默认可构造的情况下才起作用。这毫无理由地限制了类的可用性。(还有一个较小的问题,这对原始数组不起作用,但这是另一个练习)。
表达式T(),其中T是非数组完整对象的简单类型说明符或类型名称说明符类型或(可能是cv限定的)void类型,创建指定类型的右值[…]
如果Container
是const list<int>
,那么整个表达式的类型应该是list<int>::const_iterator
。如果MSVC给了你其他的东西,那就是一个bug。
也就是说,我们确实应该解决违约可构造性问题。这就是std::declval
的用武之地:
decltype(std::declval<Container&>().begin())
这不会对Container
施加任何限制,也许MSVC会正确处理这个问题。
- 迭代器和 Const 迭代器在C++?
- C++ 为 costum 类创建一个 const 迭代器
- 为什么我们在C++标准中没有"const 迭代器",而是const_iterator?
- 如何在单个模板调用中传递const_iterator和非const迭代器
- 什么时候足以将const_iterator声明为const迭代器
- const矢量和const迭代器之间的差异
- 为什么删除字符串迭代器会产生const char参考
- 将 const auto & 转换为迭代器
- 通过引用传递迭代器会给出错误:无法将参数 1 从 'const data' 转换为 'data &
- 从 const char* 到迭代器错误的"无已知转换" - 另一个例子
- 矢量迭代器与 const Vector&不兼容
- 在 C++11 中通过 const 迭代器进行破坏
- find_if() 在 const 函数中返回意外的迭代器类型
- 为什么std::distance不适用于const和nonconst迭代器的混合
- 仅为容器提供const迭代器有意义吗?
- Const与非Const迭代器的比较是否有效
- 创建const迭代器和非const迭代器
- 实现部分const迭代器
- 我应该使用 const &iterator,还是只使用迭代器?
- C++放弃迭代器(const)上的限定符