i know how to overload operator += if i am using a class for e.g.
class temp
{
public:
int i;
temp(){ i = 10; }
int operator+=(int k)
{
return i+=k;
}
};
int main()
{
temp var;
var += 67;
cout << var.i;
return 0;
}
But why cant i create a overloaded += function for basic datatype
int operator+=(int v, int h)
{
return v += (2*h);
}
int main()
{
int var = 10;
var += 67;
cout << i;
return 0;
}
i am getting error when i am compiling the above overloaded function.
It's not allowed to overload operators for primitive types. For reference see it written here:
http://www.cprogramming.com/tutorial/operator_overloading.html
Yet, you can have a similar effect by creating a "wrapper" class around the primitive type you want to overload and then creating a "conversion constructor" to go from the primitive type to your custom class and another "conversion operator" to go from your wrapper custom type back to the primitive type.
For you temp class something like this:
class temp
{
public:
int i;
temp(const int& orig){ i = orig; }
operator int(void) const { return i; }
int operator+=(int k)
{
return i+=k;
}
};
Operator overloading is not supported for primitive types. These operations are performed by direct CPU instructions. This is probably for a good reason though, as code that overloads basic arithmetic functions would be impossible to maintain.
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 want to access a primitive type array using a class.
I'm using Visual C++ 2013
class CInt
{
public:
CInt() { val_ = 0; }
CInt(int x) { val_ = x; }
private:
int val_;
};
int arr[2];
CInt index;
arr[index] = 2; // ERROR!
I tried to overload size_t() operator but still doesn't work.
Is something like that possible in C++/C++11?
I suspect you have an error, not because of your class, but where you are doing the array assignment. You must do the array assignment within a function: (this should work, assuming you overloaded the conversion operator correctly)
arr[index] = 2; // ERROR! <-- you can't do this outside a function
int main() {
arr[index] = 2; // <-- must be within a function
How did you do the overloading of the size_t() operator? The following works for me:
#include <iostream>
class CInt
{
public:
CInt() { val_ = 0; }
CInt(int x) { val_ = x; }
operator size_t() const { return val_; }
private:
int val_;
};
int main() {
int arr[2];
CInt index;
arr[index] = 2;
// output: 2
std::cout << arr[index] << std::endl;
}
I understand that we can apply increment and decrement on intrinsic data types such as:
int a;
a++;
a--;
...etc.
However, in the following codes, if I omit the & in the line operator int& ( ) { return value; }, I will get a compile error. Please explain how and why using & makes the increment possible here:
#include <iostream>
class Foo {
public:
int value;
operator int& ( ) { return value; }
};
int main ( ) {
Foo p;
p.value = 10;
p++;
std::cout << p << std::endl;
std::cin.get ( );
return 0;
}
This function definition:
operator int&() { return value; }
Allows a conversion from your class Foo to a reference to int.
This line:
p++;
Cannot increment p as type Foo as the class does not have operator++ implemented. However it is able to convert p to a reference to int via a call to operator int&() which returns a reference to value within the particular instance of Foo. The reference to value is of type int which can be incremented using ++. So the code then increments value in-place.
As to the distinction between returning an in and a reference to int, the following code shows the behaviour you mention is not distinct to the conversion oeprator:
class Foo
{
public:
Foo() : m_value(0)
{
}
int getCopy() { return m_value; }
int& getRef() { return m_value; }
private:
int m_value;
};
int main()
{
Foo f;
// Works
f.getRef()++;
// Does not work on g++ with 'error: lvalue required as increment operand`
f.getCopy()++;
}
The reason you cannot do an increment when the conversion operator returns int rather than int& is that the increment operation requires an lvalue, i.e. something that can be the target of an assignment. See here for more detail.
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);