Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
335 views
in Technique[技术] by (71.8m points)

c++ - Why is it not possible to use private method in a lambda?

Having a class like this:

class A {
public:
    bool hasGrandChild() const;

private:
    bool hasChild() const;
    vector<A> children_;
};

Why is it not possible to use a private method hasChild() in a lambda expression defined in the method hasGrandChild() like this?

bool A::hasGrandChild() const {
    return any_of(children_.begin(), children_.end(), [](A const &a) {
        return a.hasChild();
    });
}

Compiler issues an error that the method hasChild() is private within the context. Is there any workaround?

Edit: It seems that the code as I posted it originally works. I thought that it is equivalent, but the code that does not work on GCC is more like this:

#include <vector>
#include <algorithm>

class Foo;

class BaseA {
protected:
    bool hasChild() const { return !children_.empty(); }
    std::vector<Foo> children_;
};

class BaseB {
protected:
    bool hasChild() const { return false; }
};

class Foo : public BaseA, public BaseB {
public:
  bool hasGrandChild() const {
    return std::any_of(children_.begin(), children_.end(), [](Foo const &foo) {
        return foo.BaseA::hasChild();
      });
  }  
};

int main()
{
  Foo foo;
  foo.hasGrandChild();
  return 0;
}

Seems that there is a problem with fully qualified names as this does not work, but this works.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It seems to be just a GCC bug in a special case when the lambda tries to access a protected member from parent class using fully qualified name. This does not work:

class Base {
protected:
    bool hasChild() const { return !childs_.empty(); }
    std::vector<Foo> childs_;
};

class Foo : public Base {
public:
  bool hasGrandChild() const {
    return std::any_of(childs_.begin(), childs_.end(), [](Foo const &foo) {
      return foo.Base::hasChild();
    });
  }  
};

, but this works:

class Foo : public Base {
public:
  bool hasGrandChild() const {
    return std::any_of(childs_.begin(), childs_.end(), [](Foo const &foo) {
      return foo.hasChild();
    });
  }  
};

According to C++11, 5.1.2/3:

The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type — whose properties are described below. This class type is not an aggregate (8.5.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.

And then C++11, 11.7/1:

A nested class is a member and as such has the same access rights as any other member.

So the mentioned function-local lambda should have the same access rights as any other member of the class. Therefore it should be able to call a protected method from a parent class.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...