Using std::function with inherited classes - c++

I've had a little issue with some functional callbacks. How does one define a function so that I can have an f of derived x, and assign it to a derived, but given the function object wants the base class.
Can this be done? It makes sense logically. Perhaps I'm missing some form of pointer usage?
This is a simplified form of the actual software I'm working as a base reproducible.
#include <functional>
#include <iostream>
class base {
public:
std::function<void(base*)> foo;
};
class derived : public base {
public:
//EDIT:Would this work?
std::function<void(derived*)> foo;
int bar = 0;
};
void f(derived* x)
{
x->bar++;
}
int main()
{
derived d;
d.foo = f; //Issue no matching operator, LHS std::function<void(base)> , RHS void(derived)
d.foo(&d); //No match for call to std::function<void(base)>
std::cout << d.bar;
}
EDIT: fixed the invocation because silly mistake, also tweaked it slightly on what may work?

I'm not sure I understand fully what you want, but the call
d.foo();
doesn't work because it takes an argument of type base.You can work around that by defining foo to not take an argument.
class base {
public:
std::function<void(void)> foo;
};
The call in main then has to be rewritten as
int main()
{
derived d;
d.foo = [&d]{ f(d); };
...
}
which works, but may not be what you intended. See live example here;

Related

Deduce the return type of an abstract class method [duplicate]

I would like to store return value of class member function in another class.
This seems to work:
class Foo
{
public:
Foo(int) {} //non default constructor that hides default constructor
unspecified_return_type get_value();
};
class Bar
{
// stores a value returned by Foo::get_value
decltype(Foo().get_value()) value;
};
However there is a reference to default constructor of class Foo, which may not be defined in some cases. Is there any way to do it without explicitly referring to any constructor?
Yup, there is. std::declval was introduced for exactly this reason (not needing to rely on a particular constructor):
decltype(std::declval<Foo>().get_value()) value;
You could do it with the help of std::declval like the example below:
#include <iostream>
#include <utility>
struct test {
int val = 10;
};
class Foo {
public:
test get_value() { return test(); }
};
class Bar {
public:
using type = decltype(std::declval<Foo>().get_value());
};
int main() {
Bar::type v;
std::cout << v.val << std::endl;
}
LIVE DEMO
std::declval<T> converts any type T to a reference type, making it possible to use member functions in decltype expressions without the need to go through constructors.
std::declval is commonly used in templates where acceptable template parameters may have no constructor in common, but have the same member function whose return type is needed.

boost optional recognizes inheritance?

class Base {};
class Derived : public Base {};
void func(boost::optional<Base>&) {}
int main () {
boost::optional<Derived> x;
func(x);
}
will func accept both optionals: base and derived?
No, it won't work. func takes an lvalue reference to boost::optional<Base>. That means it can accept an lvalue of type boost::optional<Base>, an lvalue of a type that derives publicly and unambiguously from boost::optional<Base>, or some other type that has an operator boost::optional<Base>&(). None of those is true of boost::optional<Derived>. Class templates are not coviarant in the C++ type system - boost::optional<Derived> does not inherit from boost::optional<Base>.
It would be a different story if func took its argument by value. If it looked like:
void func(boost::optional<Base> ) { }
In that case, you could call func with a boost::optional<Derived>. But that converting constructor is marked explicit, so you would have to write:
func(boost::optional<Base>{x});
It's good that this is explicit - you are marking clear that you are (potentially) slicing x.
Even if it would work (which is likely buy I haven't checked) it would cause slicing. Only Base part would be stored in optional.
optional keeps internally a buffer of the size needed to store Base. And even if Base would be of the same size as Derived (as in your case) still it would store only Base.
EDIT:
Above answer was given for the original question which contained following code:
int main () {
boost::optional x(Derived());
func(x);
}
Such code is not correct because of two reasons:
boost::optional requires template argument
Even with the template argument it would still be function declaration.
I have ignored those issues and assumed that something like this was meant:
int main () {
boost::optional<Base> x = Derived();
func(x);
}
While that code does compile (at least Visual Studio 2013 and Boost 1.60) and causes slicing. As can be seen by running following program:
#include <boost/optional.hpp>
#include <iostream>
class Base
{
public:
virtual ~Base() { std::cout << "~Base" << std::endl; }
};
class Derived : public Base
{
public:
virtual ~Derived() { std::cout << "~Derived" << std::endl; }
};
int main()
{
boost::optional<Base> x = Derived();
}
which produces output
~Derived
~Base
~Base
The second ~Base shows that optional destroyes Base object rather than Derived object. (The ~Derived is from the temporary object Derived() as is the first ~Base.)

c++ overload method argument with original method's argument derived class

I have the following objects
#include <stdio.h>
class foo_t{ };
class bar_t: public foo_t{ };
class zoo_t: public bar_t{ };
class base_t{
public:
void dostuff(foo_t * foo){ printf("Defaulting to base\n"); };
};
class derived_t: public base_t{
public:
void dostuff(bar_t * bar){ printf("Overloading with derived\n"); };
};
int main(){
derived_t derived;
zoo_t zoo;
derived.dostuff(&zoo);
}
I see it is doing what I mean, but I would like you to confirm that this is not just a coincidence.
What I mean is that I want C++ to resolve the method that "gets closer" to the specialized class zoo_t. In this case the first ancestor found is bar_t which determines that the derived_t class method is invoked. Is this the way C++ resolves overloaded methods when arguments are both specialized and base classes?
First off, I see your functions are not virtual. I will assume that's intended and leave virtual out of discussion.
You normally don't overload a base class's member functions in a derived class; you hide them instead. Which means that base_t::dostuff is not accessible through an object-accessing expression of type derived_t. In other words, this won't compile:
int main()
{
derived_t derived;
foo_t foo;
derived.dostuff(&foo);
}
However, this will:
int main()
{
derived_t derived;
foo_t foo;
base_t& base = derived;
base.dostuff(&foo);
derived.base_t::dostuff(&foo);
}
This has other implications as well. For example the code below will print Defaulting to base:
int main()
{
derived_t derived;
zoo_t zoo;
base_t& base = derived;
base.dostuff(&zoo);
}
To summarize - which function gets called is based on the type of the expression choosing the object (the expression to the left of . or ->), and that type only. That will always work that way, so if that's the behaviour you're after, you're fine.
If you want to really overload the inherited function instead of hiding it, you can use a using declaration:
class derived_t: public base_t{
public:
void dostuff(bar_t * bar){ printf("Overloading with derived\n"); };
using bas_t::dostuff;
};
Then, the following code will work:
int main()
{
derived_t derived;
foo_t foo;
bar_t bar;
zoo_t zoo;
derived.dostuff(&foo); // calls base
derived.dostuff(&bar); // calls derived
derived.dostuff(&zoo); // calss derived
}
Live example

Calling derived class function from base class with templates without virtual

I need to generate some members/methods of a class with a script. I'm trying to break up this class in two, with base class being generated members, and derived class having hand coded members. However, I'm getting stuck in figuring out how to call derived member function D::f2() from the base class B::f1().
Here is the simplified code:
#include <cstdio>
template <typename _T>
class B {
public:
void f3() {
puts("okay");
}
void f1() {
f2(); // What C++ Magic to call f2() properly !!!
}
};
class D : public B<D> {
public:
void f2() {
f3();
}
};
int main() {
D d;
d.f1();
}
Is there any way, I can call D::f2() from B::f1() without using virtual functions ?
Added later:
If we do pointer manipulation, we will end up with injection, and I understand it's not a good idea, and I'll take the advice of not doing it. Let's stop that thread.
I am trying to find a solution using template only. I can generate any complex thing
for the generated code. It can even be a several functors etc. However the hand coded
written part should be hand-codable.
If you really really really want to do it:
static_cast<_T*>(this)->f2();
As people have mentioned, this is the curiously recuring template pattern!
This is a typical Curiously recuring template pattern. You can do:
template <typename _T>
class B {
public:
void f3() {
puts("okay");
}
void f1() {
static_cast<_T>(this)->f2();
}
};
You can use the Curiously Recurring Template Pattern.
A base class should have no notion of its children. Attempt to call a child method from base class is a sure sign of bad architecture. Virtual functions will not help you here by the way.
If you have to call a child's function from the base class you can do so just like you would do from any other function in your code. Still you will need an instance of the base class to call it on or alternatively you will have to static_cast the this pointer to a pointer of the child class type. This is a very bad idea!
There is another way, but at the cost of an ugly C style/reinterpret cast:
#include <cstdio>
#include <functional>
class B {
public:
typedef std::function<void (B*)> Function;
void f3() {
puts("okay");
}
void f1() {
_func(this);
}
Function _func;
};
class D : public B
{
public:
D()
{
_func = (void (B::*)()) &D::f2; // Here is the awfull cast I hate to do
}
void f2() {
f3();
}
};
int main() {
D d;
d.f1();
}
http://ideone.com/yOR0xT
I find this a lot less clean than the CRTP, because you have no compile time check...

C++: Binding to a base class

EDIT:
In the following code container::push takes an object of type T that derives from base as argument and stores in a vector a pointer to the method bool T::test().
container::call calls each of the stored methods in the context of to the member object p, which has type base, not T. It works as long as the called method does not refer to any member outside base and if test() is not declared virtual.
I know this is ugly and may not be even correct.
How can I accomplish the same thing in a better way?
#include <iostream>
#include <tr1/functional>
#include <vector>
class base {
public:
base(int v) : x(v)
{}
bool test() const { // this is NOT called
return false;
}
protected:
int x;
};
class derived : public base {
public:
bool test() const { // this is called instead
return (x == 42);
}
};
class container {
public:
container() : p(42)
{}
template<typename T>
void push(const T&) {
vec.push_back((bool (base::*)() const) &T::test);
}
void call() {
std::vector<bool (base::*)() const>::iterator i;
for(i = vec.begin(); i != vec.end(); ++i) {
if( (p .* (*i))() ) {
std::cout << "ok\n";
}
}
}
private:
std::vector<bool (base::*)() const> vec;
base p;
};
int main(int argc, char* argv[]) {
container c;
c.push(derived());
c.call();
return 0;
}
What you are doing with your "boost::bind" statement is to call derived::test and pass "b" as a "this" pointer. It's important to remmember that the "this" pointer for derived::test is supposed to be a pointer to a "derived" object - which is not the case for you. It works in your particular situation since you have no vtable and the memory layout is identical - but as soon as that will change, your program will likely break.
And besides, it's just plain wrong - ugly, unreadable, bug-prone code. What are you really trying to do?
[Edit] New answer to the edited question: You should use boost::bind to create a functional closure, that wraps both the object & the member function in a single object - and store that object in your collection. Then when you invoke it, it is always reliable.
If you can't use boost in your application... well, you could do something like boost::bind yourself (just look on how it is done in boost), but it's more likely that you'll get it wrong and have bugs.
To the updated question:
Calling a derived member function on a base object is Undefined Behavior. What you are trying to achieve (code) is wrong. Try to post what you need and people will help with a sensible design.
What you are doing is not correct, and in the simple example it will work, but might just raise hell (one of the possibilities for undefined behavior) in other cases.
Since base::test and derived::test are not virtual, they are two different member methods, so for simplicitly I will call them base::foo and derived::bar. In the binder code you are forcing the compiler into adapting a pointer to bar that is defined in derived as if it was actually defined in base and then calling it. That is, you are calling a method of derived on an object or type base!!! which is undefined behavior.
The reason that it is not dying is that the this pointers in base and derived coincide and that you are only accessing data present in the base class. But it is incorrect.
When you declare base::test virtual, you get the correct behavior: your most derived object in the hierarchy is base, the compiler will use the virtual dispatch mechanism and find out that base is where the final overrider for test is found and executed.
When you declare only derived::test as virtual (and not base) the compiler will try to use an inexistent virtual dispatch mechanism (usually a vtable pointer) in the handed object and that kills the application.
At any rate, all but the virtual base::test uses are incorrect. Depending on what your actual requirements are, the most probably correct way of doing it would be:
class base {
public:
virtual bool test() const;
};
class derived : public base {
public:
virtual bool test() const; // <--- virtual is optional here, but informative
};
int main()
{
derived d; // <--- the actual final type
base & b = d; // <--- optional
if ( std::tr1::bind( &base::test, std::tr1::ref(b))() ) {
// ...
}
}
Note that there is no cast (casts are usually a hint into something weird, potentially dangerous is hiding there), that the object is of the concrete type where you want the method to be called, and that the virtual dispatch mechanism guarantees that even if the
bind is to base::test, as the method is virtual, the final overrider will be executed.
This other example will more likely do funny things (I have not tried it):
struct base {
void foo() {}
};
struct derived : base {
void foo() {
for ( int i = 0; i < 1000; ++i ) {
std::cout << data[i];
}
}
int data[1000];
};
int main() {
base b;
std::tr1::bind((void (base::*)()) &derived::foo, std::tr1::ref(b))();
}