Using overloaded [] operator , we can set a value of element inside container. E.g
class Example{
public:
Example(){
arr = new int[10];
}
int operator [] ( unsigned int i) const{
return arr[i];
}
int & operator [] ( unsigned int i){
return arr[i];
}
private:
int *arr[];
}
So using
Example a;
a[0] = 0;
a[1] = 1;
a[2] = 2;
We can set the value of elements. Is it possible to do something like this with struct? If we didnt have array of int but vector of structs. e.g
struct Test{
int value;
int index;
Test( int a , int b){
value = a;
index = b;
}
}
class Example{
public:
Example(){
}
int operator [] ( unsigned int i) const{
return a[i].value;
}
Test & operator [] ( unsigned int i){
Test a(0, i );
one.push_back(a);
return a -> value;
}
private:
vector<Test> a;
}
Example a;
a[0] = 0;
a[1] = 1;
a[2] = 2;
How can i change the the value property of returned struct same way as changing/setting value using typical int container?
Yes, it is possible.
The code has an error: return a -> value; returns an int, whereas the function operator[](unsigned int i) says it will return a reference to Test. You could instead return one[one.length()-1] so that you can say example[0]->value = 1;, where example is of type Example?
The statement example[0] is a call to operator[](unsigned int i) which returns a reference to one[0], whose type is a reference to Test.
It is perfectly valid to define operator[] to return an int, and implement it the way you did above. But that's highly unintuitive; I would certainly find it very confusing because the operator [] usually returns an element of a container, not a field of an element of a container. Better to define a separate function with self-explanatory name for that, for example int& getValue(unsigned int); for the value field and int& getIndex(unsigned int) for the index field.
#include <vector>
using namespace std;
struct Test {
int value;
int index;
Test(int a, int b) {
value = a;
index = b;
}
};
class Example {
public:
Example() {}
int operator [] (unsigned int i) const {
return _a[i].value;
}
int & operator [] (unsigned int i) {
Test a(0, i);
_a.push_back(a);
return _a[i].value;
}
private:
vector<Test> _a;
};
int main() {
Example a;
a[0] = 0;
a[1] = 1;
a[2] = 2;
return 0;
}
Related
In the following code I made a template class, Its initialized in main function and I'm trying to assign char* as you can see below but It isn't working. I think the issue is in assign operator function I defined in Proxy class but I can't figure it out
#include <iostream>
using namespace std;
template <class T>
class Vector {
public:
T *p;
Vector(int size) {
p = new T[size];
}
class Proxy {
Vector &a;
int i;
public:
Proxy(Vector &a, int i) : a(a), i(i) {
}
void operator=(const T x) {
a.p[i] = x;
}
};
Proxy operator[](int i) {
return Proxy(*this, i);
}
};
int main() {
Vector<char *> sv1(2);
sv1[0] = "John";
sv1[1] = "Doe";
}
I'm getting following error;
I already tried setting parameter in assignment operator function to const, I also tried implicitly typecasting to T nothing has worked
Try this:
using namespace std;
template <class T>
class Vector {
public:
T* p;
int sz;
Vector(int size) {
p = new T[size];
sz = size;
}
template<class T>
class Proxy {
Vector<T>& v;
int i;
public:
Proxy(Vector<T>& vec, int index) :v(vec),i(index) { }
void operator= (const T val) { v.p[i] = val; }
};
Proxy<T> operator[](int index) { return Proxy<T>(*this, index); }
};
Your code will work with any basic type, (int, char, double) and pointers, but not, for example, with this:
int main() {
Vector<char*> sv1(2);
sv1[0] = "John";
sv1[1] = "Doe";
}
Firstly, the Vector points to a char*, not a string literal (const char*). You'd have to cast it using a C-style cast or a const_cast. Example:
int main() {
Vector<char*> sv1(2);
sv1[0] = const_cast<char*>("John"); //succeeds
sv1[1] = (char*)"Doe"; //succeeds
sv1[0] = "John"; //fails
sv1[1] = "Doe"; //fails
}
A string literal is always a const char* in C++.
You'll have same error writing code:
char * whatever = "something";
This code is absolutely wrong at least for string:
void operator=(const T x)
{
a.p[i] = x;
}
Step 1: allocate buffer;
Step 2: copy string to allocated buffer.
Your code is OK for primitives like char, int, etc. The following code should work:
int main() {
Vector<char> sv1(2);
sv1[0] = 'J';
sv1[1] = 'D';
}
I have a class Object that I'd like to use as if it were an int. In other words I want to pass this object to functions that accepts int, int* or int& so that the functions "see" actually ony the wrapped int value.
The code below illustrates what I want to do. I was able to write the code for int and int* but I'm not able to write the code for int&.
#include <cassert>
class Object
{
public:
int bla = 0;
int val = 0; // the int being wrapped
Object(int v) : val(v) {};
operator int() const { return val; };
int *operator &() { return &val; };
#if 1
int & operator() { return val; }; // << does not compile
#endif
};
int func(int val) {
return val * 2;
}
void Bar(int* pval, int val) {
*pval = val;
}
void Foo(int & pval, int val) {
pval = val;
}
int main() {
int val;
Bar(&val, 123);
assert(val == 123);
Foo(val, 789);
assert(val == 789);
Object o(8);
assert(func(o) == 2 * 8); // operator int()
Bar(&o, 1234); // int *operator &()
assert(o.val == 1234);
#if 1
Foo(o, 456); // << does not compile
assert(o.val == 456);
#endif
}
If #if 1 is replaced with #if 0, the code works as expected.
Could anybody point me into the right direction so Foo(o, 456); compiles?
The problem is the conversion operator, which you have the wrong syntax for.
It should be
operator int&() { return val; }
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;
}
My question is similar to this one, but not the same. That one is input array then return array. Mine is input integers, and return array.
I have an array that gets a few numbers, and makes it an array.
int makearr(int a, int b, int c){
arr[2]={a,b,c};
return?//how can I return it
}
int main(){
//and use it?
}
All I want is to make the array, and display it.
Note:
Sorry, my software doesn't support tuples.
A vector?
template <typename T>
std::vector<T> makearr (T a, T b, T c)
{
T d[] = { a, b, c };
return std::vector<T>(d, d + 3);
}
std::vector<int> x = makearr(1, 2, 3);
// access x[i]
If all manner of standard containers are verboten, then:
template <typename T> struct three { T d[3]; };
template <typename T>
three<T> makearr (T a, T b, T c)
{
three<T> d = { { a, b, c } };
return d;
}
three<int> x = makearr(1, 2, 3);
// access x.d[i]
Borrowing from here and here, I cobbled together this C++11 solution that doesn't use standard containers:
template <typename T, unsigned N>
struct argh {
argh (std::initializer_list<T> i) {
std::copy_n(i.begin(), std::min(i.size(), N), v_);
}
T & operator [] (int i) { return v_[i]; }
const T & operator [] (int i) const { return v_[i]; }
private:
T v_[N];
};
template <typename T, typename... Type>
auto makearr (T&& val, Type&&... vals) -> argh<T, 1 + sizeof...(Type)>
{
argh<T, 1 + sizeof...(Type)> arr = { val, vals... };
return arr;
}
auto x = makearr(1, 2, 3);
// access x[i]
here nothing complex is required, you just need to return an address of your first array element to a pointer,which will ultimately display the array entries. Array must be declared globally so that it is known to ptr in main().
the code is wrriten below:
int arr[3]; //Declare it globally
int main()
{
int *ptr;
ptr=makearr(2,4,5);
for(int i=0;i<3;i++)
{
cout<<*ptr<<endl;
ptr++;
}
return 0;
}
int* makearr(int a,int b,int c)
{
arr[0]=a;arr[1]=b;arr[2]=c;
return(&arr[0])
}
A pointer? You can store the integers in either an integer array or in an integer pointer. A function cannot return an array, however it can return a pointer.
int* makearr(int a, int b, int c){
int *array = new int[3];
array = &a;
array+1 = &b;
array+2 = &c;
return array;
}
int main(){
int* arr = makearr(1,2,3);
// Do something with the array. Access the elements by dereferencing the pointer variable
std::cout<<*arr<<" "<<*(arr+1);
delete arr;
return 0;
}
This code however has a potential memory leak if you do not delete the array pointer in your main(or wherever you invoke the makearr method from)
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.