C++11 Eclipse CDT:无法解析';开始';和';结束';foreach循环中的符号

C++11 Eclipse CDT:无法解析';开始';和';结束';foreach循环中的符号,c++11,foreach,eclipse-cdt,C++11,Foreach,Eclipse Cdt,每当我想要直接迭代函数返回的数据时,EclipseCDT的索引器不能正确识别foreach循环中所需的“end”和“begin”符号。当我第一次将结果放入一个临时变量时,它就起作用了 MWE: mwe.h: #include<iterator> class X { }; class Handle { }; class MyIterator: public std::iterator<X, std::input_iterator_tag> { public: ex

每当我想要直接迭代函数返回的数据时,EclipseCDT的索引器不能正确识别foreach循环中所需的“end”和“begin”符号。当我第一次将结果放入一个临时变量时,它就起作用了

MWE:

mwe.h:

#include<iterator>

class X { };
class Handle { };
class MyIterator: public std::iterator<X, std::input_iterator_tag> {
public:
    explicit MyIterator(Handle &iter) : iter_(&iter) { }
    MyIterator() { }
    MyIterator &operator++() { return *this; }
    MyIterator operator++(int) { return *this;  }
    X &operator*() { return x;  }
    X *operator->() { return &**this; }
    friend bool operator==(MyIterator a, MyIterator b) { return true; }
    friend bool operator!=(MyIterator a, MyIterator b) { return false; }
private:
    Handle *iter_;
    X x;
};

inline MyIterator begin(Handle &it) { return MyIterator(it); }
inline MyIterator end(Handle &) { return MyIterator(); }

Handle do_something() { return Handle(); }
#包括
类X{};
类句柄{};
类MyIterator:public std::iterator{
公众:
显式MyIterator(Handle&iter):iter(iter&iter){
MyIterator(){}
MyIterator&运算符++(){return*this;}
MyIterator运算符++(int){return*this;}
X&运算符*(){return X;}
X*运算符->(){return&**this;}
friend bool运算符==(MyIterator a,MyIterator b){return true;}
友元布尔运算符!=(MyIterator a,MyIterator b){return false;}
私人:
手柄*iter;
X;
};
内联MyIterator begin(Handle&it){返回MyIterator(it);}
内联MyIterator end(句柄&){return MyIterator();}
Handle do_something(){return Handle();}
代码编译和工作时没有错误,只有索引器告诉我它找不到符号。也就是说,解决这个问题并不是真的有必要,但它相当烦人

附加说明:我已经检查了许多关于CDT中索引器的其他问题,但答案并没有解决我的问题:


代码有问题还是CDT中的(已知)错误?

如果我们查看
begin

inline MyIterator begin(Handle &it) { return MyIterator(it); }
我们看到它引用了一个非常量对象。这意味着您不能将临时对象传递给函数。就像直接使用
do\u something()
时发生的情况。快速解决方案是添加一个采用右值引用的重载:


不过,您的代码还有其他可能的缺陷,特别是因为
dou\u something
按值返回。这意味着对
do\u something
的每次调用都将返回一个单独的对象,如果
do\u something
被多次调用,您将拥有具有不同数据的不同对象


还要注意的是,在C++17标准中已经弃用了。如果您需要通用类型,则应该进行专门化。

所讨论的代码实际上是一致的。它使用gcc和clang的最新版本进行编译

另一个答案中的缺陷是,它没有考虑编译器对基于范围的for循环执行的重写

[stmt.ranged]p1
表示:

基于范围的for语句

for(init-statement\u opt for range declaration:for range initializer)语句

相当于

{
    init-statement_opt
    auto &&__range = for-range-initializer ;
    auto __begin = begin-expr ;
    auto __end = end-expr ;
    for ( ; __begin != __end; ++__begin ) {
        for-range-declaration = *__begin;
        statement
    }
}
因此,在本例中,
for(auto&x:do_something()){}
被重写为:

{
    auto &&__range = do_something();
    auto __begin = begin(__range);
    auto __end = end(__range);
    for ( ; __begin != __end; ++__begin ) {
        auto &x = *__begin;
    }
}
请注意,调用
begin()
end()
的实际参数不是表达式
do\u something()
本身,而是一个隐藏(概念)变量
\u range
。由于
\uu range
是一个命名变量,因此它是表达式上下文中的一个左值,并且
begin()
end()
的左值引用参数将成功绑定到它



EclipseCDT在这段代码中给出了一个错误,这是一个bug,我刚刚解决了,很快就会解决。

谢谢,这确实有效!但是,我仍然想知道为什么它可以正确编译(在G++5和MSVC中)。也谢谢你的额外评论@0xfull我不知道为什么它显然在GCC 5上工作,但是MSVC++对该语言有一个非标准扩展,允许将临时对象绑定到非常量引用。该代码不仅可以使用GCC 5编译,还可以使用较新版本和Clang编译。我相信它是一致的,OP在EclipseCDT中发现了一个bug。请看我的答案,我在那里解释了为什么这个代码实际上是格式良好的。
{
    init-statement_opt
    auto &&__range = for-range-initializer ;
    auto __begin = begin-expr ;
    auto __end = end-expr ;
    for ( ; __begin != __end; ++__begin ) {
        for-range-declaration = *__begin;
        statement
    }
}
{
    auto &&__range = do_something();
    auto __begin = begin(__range);
    auto __end = end(__range);
    for ( ; __begin != __end; ++__begin ) {
        auto &x = *__begin;
    }
}