注意 :我写了一个"配方"根据从练习中获得的经验教训和答案&有关此页面的评论,请参阅http://www.codeproject.com/Tips/1029941/Python-like-enumeration-in-Cplusplus。
我正在使用C ++ 11为C ++ 03带来的扩展。我希望能够使用以下代码迭代容器:
$server=1
第一次迭代有x可修改,而对于第二次迭代,尝试修改x会导致编译错误。我有一些适用于非常量情况的东西:
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;
}
非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>
作为EnumIter<std::list<...>::const_iterator>
和{{1}的返回类型}。好像我需要decltype:
begin()
但是我在Visual Studio 2015 Express中遇到了编译错误:
end()
这表明我对decltype做错了,因为编译器发现了非const的begin()。有没有办法来解决这个问题?
编辑:即使使用简单的EnumIter,问题也是如此:
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_;
};
答案 0 :(得分:2)
此表达式存在一个问题:
decltype(Container().begin())
Container()
仅在Container
碰巧是默认构造时才有效。这无异于限制了你班级的可用性。 (有一个较小的问题是,这对原始阵列不起作用,但这是另一项练习)。
除此之外,代码对类类型完全有效。来自[expr.type.conv]:
表达式T(),其中T是非数组完整对象的simple-type-specifier或typename-specifier type或(可能是cv-qualified)void类型,创建指定类型[...]
的prvalue
因此,如果Container
为const list<int>
,则整个表达式的类型应为list<int>::const_iterator
。如果MSVC给你一些其他的东西,这就是一个错误。
那就是说,我们真的应该解决默认构造问题。那是std::declval
的来源:
decltype(std::declval<Container&>().begin())
这不会对Container
施加任何限制,也许MSVC会正确处理此问题。