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.
Related
Yes I know it sounds weird, but I'm looking for a way to overwrite the indirection operator to return another class object. Let me explain better:
In main.cpp I got
MyInt *V = new MyInt[10];
(*V)[3]=10;
but I would like to have it like:
MyInt *V = new MyInt[10];
V[3]=10;
In MyInt.h I've used a wrapper to catch and remove the square brackets of MyInt class and then overload the "=" operator. That's because I need a class that could store the vector and also a counter of its usage inside it. More details here.
MyInt.h
wrapper operator[] ( std::size_t i ) { return wrapper( *this, i ) ; }
The work flow is "MyInt::wrapper::operator=".
Now it works but I would like to get rid of (*V). Would be possible to remove it by overloading the indirection operator to return a wrapper object that could be passed to "wrapper::operator=" then?
I was thinking something like:
MyInt& operator*(){
return wrapper(*this)
}
but it doesn't work, I get "error: invalid initialization of non-const reference of type ‘MyInt&’ from an rvalue of type ‘test::wrapper’". I know that the indirection operator should return the same class, but I really need it that way. Any suggestion? Thanks in advance.
Note: This answer was written when OPs question was:
I would like to have it like:
MyInt V = new MyInt[10];
V[3]=10;
I'll leave this answer up in case anyone is interested in a solution for that.
#include <cstddef>
class MyInt {
public:
MyInt() = default;
MyInt(MyInt* d) : data(d) {} // constructor taking a `MyInt*`
// ... rule of 5 implementation needed here ...
MyInt& operator[](size_t idx) { return data[idx]; }
MyInt& operator=(int) { return *this; }
private:
MyInt* data = nullptr;
};
int main() {
MyInt V = new MyInt[10];
V[3]=10;
}
Note that there's no way for V to know how many elements data is pointing at.
Following the link to your earlier question, and the requirements you've added there, V[3] is undefined behaviour.
You have changed the meaning of new [] to return a pointer to a single object.
You need to completely rethink your design, such that there are 10 MyInt objects for V to point to.
struct MyCounts
{
int num_read = 0;
int num_write = 0;
};
class MyInt
{
int value;
MyCounts * counts;
static void* operator new[](size_t n){
void * ptr = malloc(sizeof(MyCounts) + n * sizeof(MyInt));
MyCounts * counts = new (ptr) MyCounts;
ptr = static_cast<void *>(counts + 1);
for (size_t i = 0; i < n; ++i, ptr += sizeof(MyInt)) {
new (ptr) MyInt{ counts };
}
return static_cast<void *>(counts + 1);
}
static void* operator delete[](void* ptr, size_t n){
for (MyInt * last = reinterpret_cast<MyInt *>(ptr) + n; --last != ptr; ) {
last->~MyInt();
}
ptr -= sizeof(MyCounts);
reinterpret_cast<MyCounts *>(ptr)->~MyCounts();
free(ptr);
}
public:
MyInt& operator=(int i) { value = i; ++counts->num_write; return *this; }
operator int() const { ++counts->num_read; return value; }
};
I would like to have it like:
MyInt* V = new MyInt[10];
V[3]=10;
You need MyInt to implement an operator= taking an int to "write" to it, and a conversion oeprator to "read" from it:
#include <iostream>
struct MyInt
{
int value;
MyInt& operator=(int v) { value = v; return *this; }
operator int() const { return value; };
};
int main()
{
MyInt *V = new MyInt[10];
V[3]=10;
std::cout << V[3] << '\n';
}
I've tried to figure out what is the purpose of & on the return type. I mean,consider the code below, what happens if i delete & from the operator overloading function.
class Container
{
public:
int numElems;
int *data;
Container(int n):numElems(n){data=new int [numElems];}
Container & operator=(const Container &rhs)
{
if(this!=&rhs)
{
if(data!=NULL)
delete [] data;
numElems=rhs.numElems;
data=new int [numElems];
for (int i=0;i<numElems;i++)
{
data[i]=rhs.data[i];
}
return *this;
}
}
};
I deleted it and compile it ,it compiled without any errors.Actualy it gives the same result in both cases for an example main:
int main()
{
Container a(3);
Container b(5);
Container c(1);
cout<<a.numElems<<endl;
cout<<b.numElems<<endl;
cout<<c.numElems<<endl;
a=b=c;
cout<<a.numElems<<endl;
cout<<b.numElems<<endl;
cout<<c.numElems<<endl;
return 0;
}
So, is there anyone who can help me about the purpose of & on the left side ? Thanks in advance.
class foo {
public:
int val;
foo() { }
foo(int val) : val(val) { }
foo& operator=(const foo &rhs) {
val = rhs.val;
return *this;
}
foo& operator++() {
val++;
return *this;
}
};
void main() {
foo f1(10), f2;
(f2 = f1)++;
std::cout << f1.val << " " << f2.val << std::endl;
}
Output:
10 11
Output when removing reference:
10 10
Returning a reference is much faster than returning a value for a large object. This is because under the hood a reference is just a memory address whereas if you return it by value it requires a deep copy
If you don't return a reference, you implicitly make an extra unnecessary copy.
I have a class something like this:
template<typename T>
class wrapper
{
public:
operator const T & () const
{
return value;
}
private:
T value;
};
I then use it with a struct like this:
struct point { float x; float y; };
//...
wrapper<point> myPoint;
std::cout << myPoint.x;// error: no member x or whatever.
I'm wondering if there's a way to allow this without having to do ((point)myPoint).x. I know that I can overload the -> operator but I'd prefer not to since its supposed to "pretend" to be a non-pointer.
You can achieve something similar with -> instead of .:
template<typename T>
class wrapper
{
public:
operator const T & () const // will this still be needed now?
{
return value;
}
T* operator->() { return &value; }
T const* operator->() const { return &value; }
private:
T value;
};
And then:
struct point { float x; float y; }
//...
wrapper<point> myPoint; // this needs to be initialised!
std::cout << myPoint->x;
You cannot make your wrapper class pretend to be a real class the way you described. The main reason is that member selection (.) operator cannot be overloaded.
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.
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);