下面是一些上下文的示例代码:
//tac.cc
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(int argc, char **argv)
{
auto lines = vector<string>{};
for(auto line = string{}; getline(cin,line); ){
lines.emplace_back(line);
};
//vector<string>::const_reverse_iterator cit = lines.rbegin();
//auto cit = lines.rbegin();
for(
decltype(lines)::const_reverse_iterator cit = lines.rbegin();
cit != lines.rend();
++cit){
cout<< *cit << endl;
};
return 0;
}在第二个for循环中,id希望具有auto的简洁性,同时从rbegin()中获取一个const_reverse_iterator。
据http://www.cplusplus.com/reference/vector/vector/rbegin/称,vector的rbegin有两个签名:
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;如果我真的用了
auto cit = lines.rbegin();我得到了rbegin的非const版本,因为编译器然后让我在没有警告的情况下修改向量(例如*cit = "foo";)。
auto是如何从rbegin的两个版本中挑选出来的。可以选第二个版本吗?
发布于 2015-07-11 21:57:53
正如0x499602d2所指出的,C++14中有cr?[begin|end]*家族,实际上,您的代码基本上出现在斯科特·迈耶的“有效的现代C++” (第13项)中,并以此作为解决方案。
目前,您可以在调用lines时“强迫”它成为const,如下所示:
auto cit = ((const decltype(lines) &)lines).rbegin();虽然还有其他方法,不涉及decltype,但我喜欢这一种,因为它对lines类型的以后的变化是不变的。
发布于 2015-07-11 22:02:03
自动选择如何从两个版本的
rbegin。可以选第二个版本吗?
这是个错误的问题。auto只是选择lines.rbegin()的类型。问题是“编译器如何选择rbegin()?”答案是,我们使用对象实例作为第一个参数对这两个函数进行过载解析。所以我们有:
reverse_iterator rbegin(vector<string>& );
const_reverse_iterator rbegin(const vector<string>& );这两个重载都是完全匹配的,但后者是对更符合cv条件的类型的引用(因为lines不是const),所以首选第一个。这就是为什么你得到了一个reverse_iterator为lines.rbegin()。auto只是高兴地演绎了它。
您想要的是强制调用本身给您一个const_reverse_iterator,这要求您将一个const对象“传递”到rbegin中。您可以明确地这样做:
auto cit = const_cast<const vector<string>&>(lines).rbegin();甚至有一个提案来使这更容易:
auto cit = std::as_const(lines).rbegin();但是更简单的是,只有一个成员函数总是返回一个const_reverse_iterator:crbegin
auto cit = lines.crbegin();https://stackoverflow.com/questions/31362150
复制相似问题