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

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.

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.

The standard (C++11, §5.1.2/3) states that
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.
Since it's a unique class type that is not a friend of A, it doesn't have access to A's private members.
What the compiler does here is create a class type that has appropriate members to store any captured variables, an appropriate operator() etc -- which is exactly what you would write yourself if you wanted to emulate lambdas in C++03. This type would certainly not have access to private members, which might make it easier to visualize why the limitation exists and why there is no workaround.
Update regarding possible workarounds:
It would be better to say "there are no workarounds using a lambda", because in general workarounds do exist although they require that you forgo the convenient lambda syntax. For example, you could:
Write a local class type that explicitly captures this along with any other locals it requires (inspired by Björn Pollex's comment below).
Write a private method instead of a lambda and pass that as the callback (e.g. using std::bind for convenience). If you want to capture locals in addition to this you can use more std::bind at the call site to do so.

Workaround:
typedef bool (A::*MemFn)(void) const;
bool A::hasGrandChild() const {
MemFn f = &A::hasChild;
return any_of(childs_.begin(), childs_.end(), [=](A const &a) {
return (a.*f)();
});
}

You can capture this explicitly and make it a "member lambda" that has access to private members.
For example, consider the following sample:
#include <iostream>
class A {
private:
void f() { std::cout << "Private"; }
public:
void g() {
[this] {
f();
// doesn't need qualification
}();
}
};
class B {
private:
void f() { std::cout << "Private"; }
public:
void g() { [] { f(); }(); } // compiler error
};
int main() {
A a;
a.g();
}

It isn't possible because the lambda is not a part of the class. It's the same as making an out-of-class function, and calling it instead of creating a lambda. Of course it doesn't have access to private members.

Related

How can I access public constructor of private nested class C++

I have a nested private classes Nested and Key and I want that I could using my add_new_object(Key, Nested) function add objects to my my_mmap multimap. But when I try to call that those classes constructors, obviously that it's inaccessible. How can I solve the problem.
class Enclosing
{
private:
class Nested {
string m_str;
double m_dbl;
bool m_boolean;
public:
Nested(string str, double dbl, bool boolean) :m_str(str), m_dbl(dbl), m_boolean(boolean) {};
};
class Key {
int m_number;
string m_name;
public:
Key(int num, string name) :m_number(num), m_name(name) {};
};
Enclosing* singleton;
std::multimap<Key, Nested> my_mmap;
public:
void add_new_object_to_mmap(Key k, Nested n) {}
static Enclosing* get_singleton() {
static Enclosing instance;
return &instance;
}
};
Thank you all in advance!
You seem to misunderstand what it means to declare a type in the private section. Or at least you are not aware of the implications of those types appearing as arguments of a public member function.
Here is your code with definitions added (without a definition for Key and Nested you cannot call their constructor at all):
#include <map>
class Enclosing
{
private:
class Nested {};
class Key {};
Enclosing* singleton;
std::multimap<Key, Nested> my_mmap;
public:
void add_new_object_to_mmap(Key k, Nested n) {}
static Enclosing* get_singleton() {
static Enclosing instance;
return &instance;
}
};
Because the type Key and Nested appear in the public interface of Enclosing they are not actually private. Only their names are private. It is possible to infer the two types from the member function:
template <typename F> struct get_types;
template <typename K,typename N> struct get_types< void(Enclosing::*)(K,N)> {
using Key = K;
using Nested = N;
};
Now you can call their constructor like you call the constructor of any other type:
int main()
{
using Types = get_types<decltype(&Enclosing::add_new_object_to_mmap)>;
using Key = Types::Key;
using Nested = Types::Nested;
Enclosing::get_singleton()->add_new_object_to_mmap(Key{},Nested{});
}
Complete Example
Finally, note that the caller doesn't even have to have names for the two types. This works as well (or with parameters when there are no default constructors):
Enclosing::get_singleton()->add_new_object_to_mmap({},{});
A type declared in the private section of another class is not private when it appears in the public interface. If you really wanted to hide the two types from the user of Enclosing then you need to do something else. See Teds answer for how to pass only parameters to be passed to their constructor to the public add_new_object_to_mmap. Then the two types can be truly private.
If you only need to be able to construct Key and Nested using a constructor taking 1 argument each, you could make add_new_object_to_mmap into a member function template and forward the arguments to the actual constructors:
#include <utility>
class Enclosing {
private:
class Key {
public:
Key(int);
bool operator<(const Key& rhs) const;
// ...
};
class Nested {
public:
Nested(double);
// ...
};
std::multimap<Key, Nested> my_mmap;
public:
template<class Karg, class Narg>
void add_new_object_to_mmap(Karg&& karg, Narg&& narg) {
my_mmap.emplace(std::forward<Karg>(karg), std::forward<Narg>(narg));
}
static Enclosing& get_singleton() {
static Enclosing instance;
return instance;
}
};
int main() {
/*here I want to call constructors*/
Enclosing::get_singleton().add_new_object_to_mmap(1, 3.141);
}
Demo
To support constructing Key and Nested with a variable amount of arguments, you could use std::piecewise_construct:
template <class... Args>
void add_new_object_to_mmap(Args&&... args) {
my_mmap.emplace(std::piecewise_construct, std::forward<Args>(args)...);
}
and forward the arguments as tuples:
int main() {
Enclosing::get_singleton().
add_new_object_to_mmap(std::forward_as_tuple(1, "Foo"),
std::forward_as_tuple("Str", 3.141, true));
}
Demo

How to create an interface to allow for the construction of different nested derived classes in C++?

My goal is to construct a derived classes nested class from the interface. However the nested classes don't have the same constructors. The question is how can I make an interface to create two different "sub-nested" classes.
Constraints:
Cannot use Heap
Nested Classes' Methods cannot be called before it is constructed
C++ 17
ITest::INestedTest* MakeTest(ITest* test, ITest::Config config)
{
// Can't call directly because it's not on the interface i.e. test.InitializeNestedTest ...
// Only workable situation is this:
if (condition)
{
auto myTest = static_cast<Test2::Test*>(test);
int p = 2;
return myTest->InitalizeNestedTest(config, p);
// ERROR function returning abstract class not allowed
} else {
auto myTest = static_cast<Test1::Test*>(test);
return myTest->InitalizeNestedTest(config);
// ERROR function returning abstract class not allowed
}
}
This static cast didn't return what I wanted previously because I was returning a pointer to a locally defined variable, which was pointed out in the comments. How am I able to return a class from this since it's an abstract class, do i need to cast it again or make multiple functions?
Test1::Test myTest;
auto myNestedTest = myTest.InitializeNestedTest(config);
I've thought of a few options but none of them seem right, or I'm not entirely sure how to implement them
Have an overloaded Virtual function for each type on the interface and then override them on the subclass (not sure if possible and doesn't seem like the right way to do it)
Extend the Config struct Test2 namespace so that it includes parameter p, so that they all have the same prototype and put it on the interface. (is it possible to "extend" the struct" from the interface?)
Maybe use a different type of cast, or do so in a different way?
I've included the definitions of my Interface and two subclasses for reference.
class ITest
{
//other things in ITest.hpp not relevant to question
public:
struct Config
{
int a;
bool enable;
};
class INestedTest
{
public:
virtual void Enable() const = 0;
virtual void Configure(Config const& config)
{
if(config.enable)
{
Enable();
}
}
};
};
namespace Test1
{
class Test : public ITest
{
public:
class NestedTest : public ITest::INestedTest
{
public:
NestedTest(Config const& config)
{
Configure(config);
}
void Enable() const override
{
//impl
}
}; // End NestedTest
NestedTest InitalizeNestedTest(Config const& config)
{
return NestedTest(config);
}
};
};
namespace Test2
{
class Test : public ITest
{
public:
class NestedTest : public ITest::INestedTest
{
public:
using Parameter = int;
NestedTest(ITest::Config const& config, Parameter p)
{
Configure(config);
}
void Enable() const override
{
//impl
}
}; // End NestedTest
NestedTest InitalizeNestedTest(Config const& config, NestedTest::Parameter p)
{
return NestedTest(config, p);
}
};
};
Maybe you could make the object static so it's declared in RAM at compile time (and not heap or stack).

How should a member class access to the member functions?

This is a question to find out the better programming practice:
In C++, say I have two classes one of which is a member class of the other, e.g.,
class SomeClass {
public:
MemberClass member_class;
void set_num(double num_) { num_ = num; }
double num() {return num_; }
private:
double num_;
}
I want the member class to have access to the member functions of the outer class, e.g.,
class MemberClass {
public:
PrintSquare() {
cout << num() * num() << endl;
}
}
I am trying to achieve this in order to reduce the number of function arguments I am passing all around the program.
The most common (and IMHO proper) way to solve this problem is, introducing an interface (or even more interfaces focusing on particular sets of method features) for the containing class, and pass that one to the 'inner' class member on construction:
struct Interface {
virtual void set_num(double num_) = 0;
virtual double num() const = 0;
virtual ~Interface() {}
};
class MemberClass {
public:
MemberClass(Interface& interface) : interface_(interface) {}
PrintSquare() {
cout << interface_.num() * interface_.num() << endl;
}
private:
Interface& interface_;
};
class SomeClass : public Interface {
public:
MemberClass member_class;
SomeClass() : member_class(*this), num_() {}
virtual void set_num(double num_) { num_ = num; }
virtual double num() const { return num_; }
virtual SomeClass() {}
private:
double num_;
};
NOTE:
Calling methods of the interface though will fail (with a runtime exception), when called from the MemberClass constructor definition.
Although the answer by Kerrek is very interesting, he himself already states this normally isn't the way to go. Common practice would be to make the inner class nested in the outer one, if possible. If the inner one needs access to the outer one in such a way that a nested connection seems natural, this would be the way to go. Construction of an Inner object would then need a reference to the object it is a member from, in order to be able to call functions on its parent:
class Outer
{
class Inner
{
Outer &parent; // consider constness
public:
Inner(Outer &_parent); //initializes the parent-reference
void innerFunction(); // can call members of parent
};
Inner inner;
public:
Outer(): inner(*this) { ... } // initialize inner
};
Depending on the standard you're using, the innerFunction now has access to all public members of Outer (C++03), or even all private members as well (C++11). See also this topic:
C++ nested classes - inner/outer relationship
EDIT: Did a quick test, and my compiler (gcc 4.7.2) also allows access to private members with older standards. Maybe someone could comment on this...
If your classes are all standard-layout, then you can take advantage of some layout guarantees that C++ makes, namely that a on object of standard layout type may be treated as if it were its own first member. For instance:
struct Foo
{
int a;
void barely_legal();
};
struct Bar
{
Foo x;
int y;
};
#include <type_traits>
void Foo::barely_legal()
{
static_assert(std::is_standard_layout<Foo>::value, "Foo");
static_assert(std::is_standard_layout<Bar>::value, "Bar");
Bar * p = reinterpret_cast<Bar *>(this);
++p->y;
}
This is unusual at best and cruel at worst, so please don't write code like this unless you have a really good reason to do so. (I know people who do have reason to do this, but I don't turn my back towards them.)

Is it possible to resolve static members similarly to overloading the member access operator for another type?

I am not sure what to call it, but is something like this possible as the commented out line reflects?
template <typename T>
class Test
{
public:
Test(T& t) : m_t(t) {}
T* operator->() { return &m_t; }
private:
T& m_t;
};
class A
{
public:
static const int integer = 0;
void function() {}
};
int main()
{
A a;
Test<A> test(a);
test->function();
// Something similar to doing Test<A>::integer?
return 0;
}
Well, why don't you do:
test->integer;
You can always access static members the same way as non-static ones (i.e. from an instance variable).
The other option would be to define in Test:
template <typename T>
class Test
{
public:
typedef T value_type;
// ...
};
In which case you will be able to do:
Test<A>::value_type::integer;
which will avoid the need of creating an instance of Test<A>.
At last, if you are using C++11 and Test follows the smart pointers conventions, then you will have:
std::pointer_traits<Test<A> >::element_type::integer;
which has the advantage to work even if you replace Test<A> with A*.
No. In C++, "overloading" only makes sense for functions. Instead of mixing static and non-static items in a class, you could try making two separate classes, both with all non-static members. Return your value from a function call, rather than using a public static member variable.

How to make a member function in an inheritance hierarchy return always the same value?

I have an inheritance hierarchy and I want to make each class in this hierarchy have a set of attributes which are particular for that class and which do not change during the run of the program. For example:
class Base
{
public:
const std::string getName() const;
bool getAttribute1() const;
int getAttribute2() const;
};
Now I want these functions to return the same result all the time. Furthermore, when another class inherits Base this class should have its own set of attributes and any instance of this derived class should have the same attributes. Also the name should be unique for each class.
I want to know a way to make this as transparent and elegant as possible. Sofar I have considered 2 ideas that I can use:
Make some lock system.
That is provide setters for these attributes, but make them throw a runtime exception when they are called more than once.
Make the getters pure virtual.
In this case, the result of the functions would not be stored inside the object itself. This would make it vaguely clear that the result depends on the dynamic type.
Both ideas sound incredibly lousy, so I need your help.
I am new to C++, but I know there are a lot of idioms and patterns to solve general problems like this one. Do you know any?
I have an inheritance hierarchy and I want to make each class in this hierarchy have a set of attributes which are particular for that class and which do not change during the run of the program
Well, then just provide the corresponding values as arguments to a class constructor, and do not expose any setter method on the public interface. This will make sure the values remain constant throughout the life-time of the object.
To protect against possible errors that would alter the value of those data members from member functions of your class (which of course can access the private data), make those data members const. Notice, that this will force you to initialize those members in the constructor's initializer list.
class Base
{
public:
// Forwarding constructor (requires C++11)
Base() : Base("base", true, 42) { }
const std::string getName() const { return _s; }
bool getAttribute1() const { return _a1; }
int getAttribute2() const { return _a2; }
protected:
// Constructor that can be called by derived classes
Base(std::string s, bool a1, int a2)
: _s(s), _a1(a1), _a2(a2) { }
private:
const std::string _s;
const bool _a1;
const bool _a2;
};
Derived classes would then just construct the base subobject with the appropriate arguments:
class Derived : public Base
{
public:
// Provide the values for the constant data members to the base constructor
Derived() : Base("derived", false, 1729) { }
};
This way you would not incur in the overhead of a virtual function call, and you won't have to rewrite similar virtual functions for each of these members in derived classes.
Make them virtual and hard-code the result which the functions should return:
class Base
{
public:
virtual const std::string getName() const { return "BaseName"; }
virtual bool getAttribute1() const { return whatEverAttributeValueYouWant; }
virtual int getAttribute2() const { return attributeValueHere; }
};
class Derived : public Base {
public:
virtual const std::string getName() const { return "DerivedName"; }
virtual bool getAttribute1() const { return whatEverOtherAttributeValueYouWant; }
virtual int getAttribute2() const { return otherAttributeValueHere; }
};
If you want to describe classes rather than objects, use (kind-of) traits:
template<class T> struct AttributeValues;
template<> struct AttributeValues<Base> {
static const std::string name () { return "BaseName"; }
};
template<> struct AttributeValues<Derived> {
static const std::string name () { return "DerivedName"; }
};
//...
auto nameBase = AttributeValues<Base>::name ();
auto nameDerived = AttributeValues<Derived>::name ();