c++ pointers to operators - c++

I want to write a pointer in c++ (or in c++0x), that will points to a operator of a class lets say A or B.
Is there any method to do it?
Of course there is a syntax like
int (A::*_p) ();
but it doesn't solve this problem. I want to make general pointer, not specifying the base class for it - only pointer for "operator function"
#include <thread>
#include <iostream>
using namespace std;
class A
{
public:
int operator()()
{
return 10;
}
};
class B
{
public:
int operator()()
{
return 11;
}
};
int main()
{
A a;
int (*_p) ();
_p = a.operator();
cout << _p();
B b;
_p = b.operator();
cout << _p();
}

No, you can't do this. The class type is a part of the type of the operator member function.
The type of A::operator()() is different from the type of B::operator()(). The former is of type int (A::*)() while the latter is of type int (B::*)(). Those types are entirely unrelated.
The closest you can get is by using something like the C++0x polymorphic function wrapper function (found in C++0x, C++ TR1, and Boost) and by using bind to bind the member function pointer to a class instance:
std::function<int()> _p;
A a;
_p = std::bind(&A::operator(), a);
std::cout << _p();
B b;
_p = std::bind(&B::operator(), b);
std::cout << _p();

Related

C++ - calling a member function of another class using a pointer

I'm testing, trying to call a member function being passed as a parameter,
the member function has to be one of another class.
this is an example, which gives an error:
"pointer-to-member selection class types are incompatible ("B" and
"A")"
This is the code, what am I doing wrong?
#include <iostream>
using namespace std;
class A {
private:
public:
void fA(int x) {
cout << "hello" << endl;
}
void fB(int x) {
cout << "good bye" << endl;
}
A() {
}
};
class B {
private:
void (A:: * f)(int) = NULL;
public:
B(void (A:: * f)(int)) {
this->f = f;
}
void call() {
(this->*f)(10); //What's wrong here?
}
};
A a = A();
B b = B(&(a.fA));
B b2 = B(&(a.fB));
int main(void) {
b.call();
b2.call();
}
&(a.fA) is not legal C++ syntax. &A::fA is. As you can see, there is no object of type A anywhere of this syntax. &A::fA is just a pointer to a member function, not a pointer-to-member-together-with-an-object combo.
Now in order to call that pointer-to-member, you need an object of class A. In class B, you don't have any. You need to get one in there somehow, and call the function this way:
(a->*f)(10);
where a is a pointer to that object of class A.

Polymorphic unique_ptr class member

I would like to have a unique_ptr class member that points to the base class, but later in the constructor through polymorphism can be changed to point to a sister class that also derives from the same base class.
While I don't get any errors in the constructor setting this polymorphism, it does not seem to work correctly, since I get error messages that my polymorphic pointer can't find a member of the sister class to which I thought the pointer was now pointing.
How do I correctly achieve polymorphism here?
class A {
int bar;
};
class B : public A {
int foo;
};
class C: public A {
C();
std::unique_ptr<A> _ptr; // changing to std::unique_ptr<B> _ptr removes the "class A has no member 'foo'" error
};
C::C() : A()
{
_ptr = std::make_unique<B>(); // no errors here
int w = _ptr->foo; // class A has no member 'foo'
}
When you assign
_ptr = std::make_unique<B>();
This works because B is a derived class of A, however _ptr is still a unique_ptr to the base class. You can't change the type of a variable after it's declared.
So what are your options?
Because you know that _ptr stores a pointer to the derived class B, you can do a cast after dereferencing it:
_ptr = std::make_unique<B>();
// derefence the pointer, and cast the reference to `B&`.
B& reference_to_sister = (B&)(*_ptr);
int w = reference_to_sister.foo;
If you take this approach, you'll have to somehow keep track of which derived class is in _ptr, or you'll run the risk of running into bugs.
Alternatively, if you're using C++17, you can use std::variant:
class C : public A {
void initialize(A& a) {
// Do stuff if it's the base class
}
void initialize(B& b) {
// Do different stuff if it's derived
int w = b.foo;
}
C() {
_ptr = std::make_unique<B>(); // This works
// This takes the pointer, and calls 'initialize'
auto initialize_func = [&](auto& ptr) { initialize(*ptr); };
// This will call 'initialize(A&)' if it contains A,
// and it'll call 'initialize(B&)' if it contains B
std::visit(initialize_func, _ptr);
}
std::variant<std::unique_ptr<A>, std::unique_ptr<B>> _ptr;
};
In fact, if you use std::variant this will work even if A and B are completely unrelated classes.
Here's another short variant example
#include <variant>
#include <string>
#include <iostream>
void print(std::string& s) {
std::cout << "String: " << s << '\n';
}
void print(int i) {
std::cout << "Int: " << i << '\n';
}
void print_either(std::variant<std::string, int>& v) {
// This calls `print(std::string&) if v contained a string
// And it calls `print(int)` if v contained an int
std::visit([](auto& val) { print(val); }, v);
}
int main() {
// v is empty right now
std::variant<std::string, int> v;
// Put a string in v:
v = std::string("Hello, world");
print_either(v); //Prints "String: Hello, world"
// Put an int in v:
v = 13;
print_either(v); //Prints "Int: 13"
}

Why does std::bind prevent late binding when using pass-by-reference? [duplicate]

This question already has an answer here:
Does std::bind discard type information of parameters in C++11?
(1 answer)
Closed 5 years ago.
I have a base class, a derived class, and a virtual member function. I also have a function which takes a base class reference and makes a polymorphic call to the member function:
#include <iostream>
#include <functional>
class Base
{
public:
Base() {}
virtual int getnum() { return 1; }
};
class Derived : public Base
{
public:
Derived() {}
virtual int getnum() { return 2; }
};
int getnumref(Base& b) { return b.getnum(); }
int main()
{
Derived d;
Base& bref = d;
std::cout << getnumref(bref) << std::endl;
}
Here, late binding occurs, and the output is 2.
But if I now add the following lines to the main() function in order to pre-define the argument to the function, and then call it:
std::function<int()> boundgetnumref = std::bind(getnumref, bref);
std::cout << boundgetnumref() << std::endl;
then the output of the last line is 1, i.e. here, early binding occurs, and the member function of the base class is called.
If I use pointers, i.e.
//...
int getnumptr(Base* b) { return b->getnum(); }
//...
int main()
{
Derived d;
Base* bptr = &d;
std::cout << getnumptr(bptr) << std::endl;
std::function<int()> boundgetnumptr = std::bind(getnumptr, bptr);
std::cout << boundgetnumptr() << std::endl;
}
then the output of both cout calls is 2.
Why does early binding take place when I use pass-by-reference together with std::bind, and not otherwise?
std::bind stores captured arguments by value causing a slicing copy of Derived to Base.
If you just pass std::reference_wrapper (a pointer) that would copy the pointer, so that slicing copy does not happen:
std::function<int()> boundgetnumref = std::bind(getnumref, std::ref(bref));
Prefer lambdas though, they are the best practice: easier to write, read and more efficient:
auto boundgetnumref = [&bref]() { return getnumref(breg); }

Class non-static method pointer to global function

I'm trying to point a class method to a global function, i've seen this
but how i can't do it without instance?.
Consider this:
class x
{
public:
int(x::*GetVal)(int);
};
int RtX(int a)
{
return a * 4;
}
// declaration
int(x::*GetVal)(int) = (int(x::*)(int))&::Rtx; // :: global? // error
int main()
{
x a;
cout << (a.*GetVal)(4) << endl;
}
This returns me the error:
[Error] invalid cast from type 'int ()(int)' to type 'int
(x::)(int)'
x::GetX is a pointer to member. These are deeply complicated beasts, and you can't get them to point to non-member functions. The following code will work:
#include <iostream>
int RtX(int a) // Global non-member function
{
return a * 4;
}
class x
{
public:
int(x::*GetVal)(int);
// This is an instance member function which acts as a proxy and calls the
// the global function
int RtX(int a) { return ::RtX(a); }
};
int main()
{
x a;
a.GetVal =&x.RtX; // Assign the member variable. Could do this in the
// constructor. **NOTE** No casts!
std::cout << (a.*GetVal)(4) << std::endl;
}
If you find yourself reaching for a cast when dealing with function pointers and pointers-to-member-functions, stop - you are almost certainly doing it wrong, and while it will compile, it is very likely not to run properly.
Alternatively, as noted in the comments, use std::function.
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
std::function<int(int)> GetVal;
// Initialize GetVal in the constructor.
x() : GetVal(RtX)
{}
// Alternatively, you can initialize the variable in with a default
// initialization. You can also declare the member const if you don't want to
// change it later.
const std::function<int(int)> gv = RtX;
/*
};
int main()
{
x a;
std::cout << a.GetVal(4) << std::endl;
}
Non static member functions need an instance in order to be called. You might consider using a static function member instead and if you also use std::function, you might get a simple code to assign your member function without instance:
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
static std::function<int(int)> GetVal;
};
std::function<int(int)> x::GetVal = RtX;
int main()
{
x a;
std::cout << (a.GetVal)(4) << std::endl;
}

Pointing a variable to a member function from a different class type

In C++, how do i call a method member of class A from a class B, using a pointer? By the way Class A and B are of different types.
I read that when a pointer is pointing to member function it can only point member functions within the class. But how can i point to a member function outside the class?
for example:
class A
{
public:
int add(int x)
{
return x+x;
}
};
int main()
{
typedef int (A::*pointer)();
pointer func = &A::add;
A objt;
B objt2;
obt2.*func(2);// the compiler give me an error of incompatible with object type ‘B’
return 0;
}
I think you can run it as follows:
(*func)(&objt, 2)
Better choice would be to use boost::bind/boost::function instead:
boost::function<int(int)> func = boost::bind(&A::add, &objt, _1);
func(2);
I just noticed that you're trying to make it run as if it were a method of class B.
It's completely nonsensical, but if you don't care about correctness and like to live dangerously with completely unpredictable results, it's easier to do this:
((A *) &objt2)->add(2);
If B uses A (calls some A's member) then B depends on A and you can implement this by simply providing B with pointer to A through which it can call A's methods - see class B1 below in the code.
You can wrap the call of A's member into a separate object - functor. You can create generic solution by implementing it as a template class and providing address of the object A, address of the method and argument. For this, see implementation of class B2.
class A
{
public:
int add(int x)
{
return x+x;
}
};
typedef int (A::*MEMFN)(int);
class B1
{
public:
void InvokeAAdd(A* pA, int x)
{
cout << "result = " << pA->add(x) << endl;
}
};
template<class T, typename TMemFn, typename TArg, typename TRetVal>
class B2
{
T* pT;
TMemFn memFn;
TArg arg;
public:
B2(T* pT, TMemFn memFn, TArg arg) :
pT(pT), memFn(memFn), arg(arg){}
TRetVal operator()()
{
return (pT->*memFn)(arg);
}
};
int main()
{
A a;
B1 b;
b.InvokeAAdd(&a, 2);
B2<A, MEMFN, int, int> b2(&a, &A::add, 2);
cout << "result (via functor) = " << b2() << endl;
return 0;
}
Output:
result = 4
result (via functor) = 4