C++ continues to surprise me.
Today i found out about the ->* operator. It is overloadable but i have no idea how to invoke it. I manage to overload it in my class but i have no clue how to call it.
struct B { int a; };
struct A
{
typedef int (A::*a_func)(void);
B *p;
int a,b,c;
A() { a=0; }
A(int bb) { b=b; c=b; }
int operator + (int a) { return 2; }
int operator ->* (a_func a) { return 99; }
int operator ->* (int a) { return 94; }
int operator * (int a) { return 2; }
B* operator -> () { return p; }
int ff() { return 4; }
};
void main()
{
A a;
A*p = &a;
a + 2;
}
edit:
Thanks to the answer. To call the overloaded function i write
void main()
{
A a;
A*p = &a;
a + 2;
a->a;
A::a_func f = &A::ff;
(&a->*f)();
(a->*f); //this
}
Just like .*, ->* is used with pointers to members. There's an entire section on C++ FAQ LITE dedicated to pointers-to-members.
#include <iostream>
struct foo {
void bar(void) { std::cout << "foo::bar" << std::endl; }
void baz(void) { std::cout << "foo::baz" << std::endl; }
};
int main(void) {
foo *obj = new foo;
void (foo::*ptr)(void);
ptr = &foo::bar;
(obj->*ptr)();
ptr = &foo::baz;
(obj->*ptr)();
return 0;
}
The overloaded ->* operator is a binary operator (while .* is not overloadable). It is interpreted as an ordinary binary operator, so in you original case in order to call that operator you have to do something like
A a;
B* p = a->*2; // calls A::operator->*(int)
What you read in the Piotr's answer applies to the built-in operators, not to your overloaded one. What you call in your added example is also the built-in operator, not your overloaded one. In order to call the overloaded operator you have to do what I do in my example above.
Like any other opperator, you can also call it explicitly:
a.operator->*(2);
Related
My code is as follows:
class Foo{
public:
int operator()(int i)
{
return 1;
}
int operator++(int i)
{
return 1;
}
};
int main()
{
Foo foo;
int a = foo++;
int b = foo(0);
float c = 0;
}
The problem is that I am not able to watch foo(0):
foo++ is visible normally.
I think the reason is that overloaded function call operator becomes a FunctionObject type (see here https://en.cppreference.com/w/cpp/language/operators).
Is it possible to watch it?
As n-1-8e9-wheres-my-share-m commented, foo.operator()(0) works for me:
What operator overload would allow me to do this? Is there a "no operator" operator? I understand that to get the value I must do some kind of call(), but I'd like to know if it's possible to clean it up.
template<typename T>
class Stuff{
private:
T stuff{};
public:
T& operator () (){
return stuff;
}
T& operator = (const T& val){
stuff = val;
return stuff;
}
};
int main()
{
int myInt = 0;
Stuff<int> stuff;
stuff = myInt;
myInt = stuff(); // <- works
myInt = stuff; // <- doesn't, is there a way to do it ?
}
Yes there is a way: build a user-defined conversion function in Stuff:
operator T() const
{
std::cout << "I'm here";
return 0;
}
Because myInt is a T type, this function will be called in the assignment myInt = stuff.
Came across the following example:
https://godbolt.org/g/yYgZox
#include <iostream>
struct A {
operator void* (){ return nullptr; }
};
A a;
A& getA () {
return a;
}
int main(int, char**)
{
int x = 0;
// this works
if (std::cout << x) {
return 1;
}
// this works only because we have operator void* defined
if (getA()) {
return 2;
}
return 0;
}
Why it is OK for the compiler to cast a reference to void* when such defined as a member function?
In the below code snippet
#include <iostream>
class A
{
public:
A(int i) : m_i(i) { }
public:
int operator()(int i = 0) const
{
return m_i + i;
}
operator int () const
{
return m_i;
}
operator float () const
{
return 0.0;
}
private:
int m_i;
friend int g(const A&);
};
int f(char c)
{
return c;
}
int g(const A& a)
{
return a.m_i;
}
int main()
{
A f(2), g(3);
int i = f;// call 1
std::cout << f(1) << g(f) << std::endl;// call 2
return 0;
}
I gave some comments like call 1 and call 2 in the main function.
I understood why operator int is called at call 1.
But I could not understand why at // call 2
Can some body explain me why it is so.
The function g is hidden by the g (of type A) in scope. So g(f) converts f to int then calls g.operator()(int) with the result of the conversion.
When you call g(f), A::operator()(int i=0) is called for g.
f must therefore be converted into an int, which is done via A::operator int() .
std::cout << f(1) << g(f) << std::endl;
Let's break this down into function calls instead of operators. (This might not be technically correct syntax.)
int temp1 = f.operator()(1);
ostream& temp2 = std::cout.operator<<(temp1);
// By the implementation of ostream::operator<<, temp2 is a reference to std::cout.
// The compiler doesn't know this, though, and must treat it as if it could be different.
int temp3 = f.operator int(); // Typecast since A::operator() expects an `int`.
int temp4 = g.operator()(temp3);
ostream& temp5 = temp2.operator<<(temp4);
// temp5 is another reference to std::cout.
temp5.operator<<(std::endl);
// Result discarded.
There is something that is troubling my brain since a moment: I am trying to overload the [] operator based on the return type. Here is what I need to do:
class A {
private:
double* data_;
int N_;
public:
A (N=0):N_(N){
data_ = new double[N];
}
~A {delete[] data_;}
double operator[] (const int i) {
return data_[i];
}
double* operator[] (const int i) {
return &data[i]; // for example; in fact here i need to return some block of data_
}
};
This code won't compile; and that is my problem. Can someone help me to solve this problem?
PS: I know how to overload normal functions on the return type for example:
int foo ();
string foo ();
I used some tricks that I read in this forum. In this way:
struct func {
operator string() { return "1";}
operator int() { return 2; }
};
int main( ) {
int x = func(); // calls int version
string y = func(); // calls string version
double d = func(); // calls int version
cout << func() << endl; // calls int version
func(); // calls neither
}
Thank you.
Two method overloads must have different signatures. The return type is not part of the signature of a method.
You can use the same "trick" that you use for functions, that is use a proxy object with conversion operators:
class A
{
private:
double* data_;
int N_;
public:
A (int N = 0)
: N_(N), data_(new double[N])
{}
~A() { delete[] data_; }
struct proxy
{
int i;
double * data;
operator double() const
{
return data[i];
}
operator double*()
{
return &data[i];
}
operator double const *() const
{
return &data[i];
}
};
proxy operator[] (int const i) {
proxy p { i, data_ };
return p;
}
proxy const operator[] (int const i) const {
proxy p { i, data_ };
return p;
}
};
int main()
{
{
A a(12);
double d = a[0];
double * pd = a[0];
}
{
A const ca(12);
double d = ca[0];
//double * pd = ca[0]; // does not compile thanks to overloads on const
double const * pcd = ca[0];
}
}
However, I would argue that this is a terrible idea. Having your operator[] return either a value or a pointer to this value is guaranteed to confuse the users of your class, in addition to making it impractical to use in expressions where both types are possible. For instance, std::cout << a[0]; would not compile (ambiguous overloads).
Probably you need something like that:
class A {
private:
double* data_;
int N_;
... // other stuff
public:
double operator[] (const int i) const { // note const here
return data_[i];
}
double& operator[] (const int i) { // note reference here
return data_[i];
}
};
also operator should be public to have a sense.