I need some help with operator assignment. This is code:
Sinusoid.h:
class Sinusoid : public Component
{
float fs, f, A, fi;
int N;
double *array;
public:
Sinusoid(float fs, float f, float Ts, float fi, float A);
void count(int type=1);
void clear();
~Sinusoid();
double *getArray() { return this->array; }
double*& operator=(Sinusoid* const &rhs) {
return rhs->array;
};
};
main.cpp:
#include "headers.h"
int main()
{
int N = 1000 * 2.5;
Sinusoid *sinus = new Sinusoid(1000, 15, 2.5, (M_PI / 4), 0.7);
double **answers = new double*[7];
for (int i = 0; i < 7; i++) {
answers[i] = new double[N];
}
//lab1
//Zad1
sinus->count(1);
answers[0] = sinus;
return 0;
}
When i build this code i've got the following problem:
C2440 '=': cannot convert from 'Sinusoid *' to 'double *' main.cpp:15
I know that i can assign two classes with overloaded operator "=" but i want to take a private member of class (double *array;). I know that i can do it by "getArray()" method but i want to learn more "beautiful" practice. Hope you will help me.
Thank you.
Your double*& operator=(Sinusoid* const &rhs) operator doesn't do what you apparently think it does.
An operator= member function allows you to have an instance of the class (Sinusoid) on the left side of an assignment and an instance of the parameter type (Sinusoid*) on the right side. So what you wrote would let you do:
Sinusoid* pointer = whatever;
Sinusoid object;
object = pointer;
Obviously that's not what you intended. (And probably not something you'll ever want.)
The return type of the operator= doesn't have any influence on this fundamental usage. All it means is that the result of object = pointer is then a double*&. So it would let you write:
double* foo;
foo = (object = pointer);
And that's still not helpful for what you want.
Since answers[0] is a pointer, there's no way to create a custom assignment operator for it. However the language has a different mechanism which can be used here. You can create an implicit conversion operator for your class so that compiler is allowed to convert/decay it into a different type when reasonable. Try adding the following to your class:
operator double* () {
return rhs->array;
}
That should work for the case you want.
Although personally I don't think there's anything wrong with leaving the usage to require calling getArray() in the first place. Sometimes the clarity of an explicit function call can make it easier to read what's actually going on.
Try...
class Sinusoid : public Component {
...
operator double*() {
return array;
}
and the usage
answers[0] = *sinus;
Related
I'm fairly new to C++. I've searched extensively but I couldn't make it work.
I've defined a custom type called vec_t:
class FloatType {
private:
float value;
public:
FloatType() : value(0.0f) {}
FloatType(float v) : value(v) {}
//operator float() { return value; }
//operator float() { return value; }
//explicit operator const float* () { return &value; }
//operator float* () const { return &value; }
//operator const float* () { return &value; }
//operator const float() { return (const float)value; }
//operator const float*() { return &value; }
};
typedef FloatType vec_t;
I've also created a function which takes a const float * as its only argument:
void Create(const float* vColor = NULL);
void Create(const float* vColor) {
//...
}
Now, when calling the function like so:
vec_t a = { 2.5f };
vec_t* b = &a;
Create(b);
Visual Studio Community 2019 (v142) is complaining:
argument of type "vec_t *" is incompatible with parameter of type "const float *"
Now, casting it to const float * on the spot gets it done:
Create((const float *)b);
But, my goal is to have an implicit casting operator to implicitly convert from my type to const float *, but no matter my efforts, I can not seem to have it right.
All operator comments were my attempts and they all have valid syntax, but they don't make the problem go away.
What am I not understanding?
I want to be able to handle this from within the FloatType class itself, and to my knowledge, an implicit casting operator is the way to do so.
Don't guide me to another approach, this is purely for practice and exercise.
The problem is that while vec_t is a class type that can have conversion operators defined, vec_t * is a primitive type (a pointer), and no user-defined conversions apply to it.
Some possible solutions:
Don't pass around pointers to vec_t, pass them by value instead. If necessary, use std::move to avoid potentially expensive copies. This boils down to just Create(a). john's answer explains this in more detail.
Dereference the pointer, as in Create(*b), to allow the compiler to find your user-defined conversions.
Add a float * data() member function to vec_t, just like std::vector, and call that to get at the underlying data: Create(b->data())
Don't use your own vector type and just use std::array<float, N> for statically-sized vectors and std::vector<float> for dynamically sized ones. This is likely the best solution. To get a pointer to the raw data, use vec.data(). (Again, take advantage of these types' value semantics to get memory safety. Move / copy them, don't use raw pointers.)
If you want something really ugly that you shouldn't do: Create(b->operator float *()).
Your vec_t type is not a pointer, so you should not be using a pointer as the argument when calling Create():
class FloatType
{
private:
float value;
public:
...
operator const float* () const { return &value; }
// const here ^^^^^
};
typedef FloatType vec_t;
vec_t a = { 2.5f };
Create(a);
For some reason, you introduced the pointer b, that's the main reason your code doesn't work.
Also, you should have an extra const on your conversion operator, as I've indicated above.
I have two classes Polynom and Fraction.
I need to do a template for Polynom, for using Fraction like coefficient in Polynom, like: 3/4 x^0 + 5\6 x^1 etc.
I understood how to use a simple type like double or int, but how to get this to work for a class I have no idea, and can't find a material on this theme.
class Fraction {
private:
int numerator, denominator;
public:
Fraction();
Fraction(int, int);
Fraction(int);
}
template<class T>
class PolynomT {
private:
int degree;
T *coef;
public:
PolynomT();
explicit PolynomT(int, const T * = nullptr);
~PolynomT();
};
template<class T>
PolynomT<T>::PolynomT(int n, const T *data): degree(n) {
coefA = new T[degree+1];
if (data == nullptr) {
for (int i = 0; i < degree+1; ++i)
coefA[i] = 0.0;
}
else {
for (int i = 0; i < degree + 1; ++i)
coefA[i] = data[i];
}
}
/*Problem here*/
int main() {
PolynomT<Fraction> a(); // what need to pass on here in arguments?
// how should the constructor look like?
/*Example*/
PolynomT<Fraction> b();
PolynomT<Fraction> c = a + b; // or something like this.
}
So, how to do the class constructor for Fraction in PolynomT, and how to do overloading operators for this?
The problem with the coefA[i] = 0.0 assignment in the PolynomT constructor happens because Fraction does not have a constructor that takes a double, nor does it have an assignment operator that takes a double. There are several possible solutions.
Change from raw memory management to std::vector for coefA.
std::vector<T> coefA;
// Then resize appropriately in the constructor
This would automatically fill all the elements with a default constructed object, so you wouldn't need to do anything if data == nullptr.
Another possibility is to change the assignment to
coefA[i] = T();
This will assign a default constructed object of the type (0.0 for doubles).
What are the basic rules and idioms for operator overloading has detailed information on overloading operators.
I have a project that wants me to make a BigNum class in c++ (university project)
and it said to overload operator bracket for get and set
but the problem is if the set was invalid we should throw an exception the invalid is like
BigNum a;
a[i]=11;//it is invalid because its >9
in searching I found out how to make the set work
C++ : Overload bracket operators [] to get and set
but I didn't find out how to manage setting operation in c# you easily can manage the set value what is the equivalent of it in c++
to make it clear in C# we can say
public int this[int key]
{
set
{
if(value<0||value>9)throw new Exception();
SetValue(key,value);
}
}
New Answer
I have to rewrite my answer, my old answer is a disaster.
The check should happen during the assignment, when the right hand side (11) is available. So the operator which you need to overload is operator=. For overloading operator=, at least one of its operands must be an user defined type. In this case, the only choice is the left hand side.
The left hand side we have here is the expression a[i]. The type of this expression, a.k.a the return type of operator[], must be an user defined type, say BigNumberElement. Then we can declare an operator= for BigNumberElement and do the range check inside the body of operator=.
class BigNum {
public:
class BigNumberElement {
public:
BigNumberElement &operator=(int rhs) {
// TODO : range check
val_ = rhs;
return *this;
}
private:
int val_ = 0;
};
BigNumberElement &operator[](size_t index) {
return element_[index];
}
BigNumberElement element_[10];
};
OLD answer
You can define a wapper, say NumWapper, which wraps a reference of BigNum's element. The operator= of BigNum returns the wrapper by value.
a[i]=11;
is then something like NumWrapper x(...); x = 11. Now you can do those checks in the operator= of NumWrapper.
class BigNum {
public:
NumWrapper operator[](size_t index) {
return NumWrapper(array_[index]);
}
int operator[](size_t index) const {
return array_[index];
}
};
In the NumWrapper, overload some operators, such as:
class NumWrapper {
public:
NumWrapper(int &x) : ref_(x) {}
NumWrapper(const NumWrapper &other) : ref_(other.ref_) {}
NumWrapper &operator=(const NumWrapper &other);
int operator=(int x);
operator int();
private:
int &ref_;
};
You can also declare the NumWrapper's copy and move constructor as private, and make BigNum his friend, for preventing user code from copying your wrapper. Such code auto x = a[i] will not compile if you do so, while user code can still copy the wrapped value by auto x = static_cast<T>(a[i]) (kind of verbose though).
auto &x = a[i]; // not compiling
const auto &x = a[i]; // dangerous anyway, can't prevent.
Seems we are good.
These is also another approach: store the elements as a user defined class, say BigNumberElement. We now define the class BigNum as :
class BigNum {
// some code
private:
BigNumberElement array_[10];
}
We need to declare a whole set operators for BigNumberElement, such as comparison(can also be done through conversion), assignment, constructor etc. for making it easy to use.
auto x = a[i] will now get a copy of BigNumberElement, which is fine for most cases. Only assigning to it will sometimes throw an exception and introduce some run-time overhead. But we can still write auto x = static_cast<T>(a[i]) (still verbose though...). And as far as I can see, unexpected compile-time error messages is better than unexpected run-time exceptions.
We can also make BigNumberElement non-copyable/moveable... but then it would be the same as the first approach. (If any member functions returns BigNumberElement &, the unexpected run-time exceptions comes back.)
the following defines a type foo::setter which is returned from operator[] and overloads its operator= to assign a value, but throws if the value is not in the allowed range.
class foo
{
int data[10];
public:
void set(int index, int value)
{
if(value<0 || value>9)
throw std::runtime_error("foo::set(): value "+std::to_string(value)+" is not valid");
if(index<0 || index>9)
throw std::runtime_error("foo::set(): index "+std::to_string(index)+" is not valid");
data[index] = value;
}
struct setter {
foo &obj;
size_t index;
setter&operator=(int value)
{
obj.set(index,value);
return*this;
}
setter(foo&o, int i)
: obj(o), index(i) {}
};
int operator[](int index) const // getter
{ return data[index]; }
setter operator[](int index) // setter
{ return {*this,index}; }
};
If what you are trying to do is overload [] where you can input info like a dict or map like dict[key] = val. The answer is actually pretty simple:
lets say you want to load a std::string as the key, and std::vector as the value.
and lets say you have an unordered_map as your underlying structure that you're trying to pass info to
std::unordered_map<std::string, std::vector<double>> myMap;
Inside your own class, you have this definition:
class MyClass{
private:
std::unordered_map<std::string, std::vector<double>> myMap;
public:
std::vector<double>& operator [] (std::string key) {
return myMap[key];
}
}
Now, when you want to load your object, you can simply do this:
int main() {
std::vector<double> x;
x.push_back(10.0);
x.push_back(20.0);
x.push_back(30.0);
x.push_back(40.0);
MyClass myClass;
myClass["hello world"] = x;
double x = myClass["hello world"][0]; //returns 10.0
}
The overloaded [] returns a reference to where that vector is stored. So, when you call it the first time, it returns the address of where your vector will be stored after assigning it with = x. The second call returns the same address, now returning the vector you had input.
Say I have two classes, One and Two. One and Two are essentially the same, but Two can convert into One.
#ifndef _ONE_H_
#define _ONE_H_
class One
{
private:
float m_x;
float m_y;
public:
One();
One(float x, float y);
};
#endif
#ifndef _TWO_H_
#define _TWO_H_
#include "One.h"
class Two
{
private:
float m_x;
float m_y;
public:
Two();
Two(float x, float y);
operator One() { return One(m_x, m_y); }
operator One* () { return &One(m_x, m_y); }
operator One& () const { return *this; }
float GetX(void) { return m_x ;}
float GetY(void) { return m_y ;}
void Print();
};
#endif
Two has access to One, but One does not have access to Two. In the main.cpp I have:
One a(4.5f, 5.5f);
Two b(10.5, 7.5);
One * c = &b;
I get an error if I try to do the pointer of a One to the address of a Two. The error is "error C2440: 'initializing' : cannot convert from 'Two *' to 'One *'"
I cannot for the life of me figure out how to do this, if it is even possible. Any help would be appreciated.
EDIT: Added a new line to Two.h with operator One& () const { return *this; }. The function I'm attempting to use to get this conversion operator to work is void TestRefConstPrint(const One &testClass); With main below, this presents a new error for "cannot convert parameter 1 from Two' to 'const One &'.
Inside main I do:
int main()
{
Two b(10.5, 7.5);
TestRefConstPrint(b);
return 0;
}
Your conversion operators enable the conversions Two -> One and Two -> One*. You are trying to perform a different conversion, Two* -> One*.
To use your operator One() conversion operator to perform a Two -> One conversion, just do this:
One c = b;
If you really want to do a Two* -> One* conversion, you can, with an explicit cast:
One * c = (One *)&b;
or using C++-style casts:
One * c = reinterpret_cast<One *>(&b);
Note, however, that this does not use either of your conversion operators, and does a very different thing from the Two -> One conversion: it does not create a new object, it makes a pointer-to-One that points to the memory occupied by a Two object. This is generally a bad idea, and it's unlikely that you want to do this.
Finally, a comment about your operator One*(): it returns a dangling pointer (a pointer to a local variable which goes out of scope when the function returns). I assume you wrote it in your attempt to get the Two* -> One* conversion to work. You should remove it because it does not do what you want.
I'm using a 2D matrix in one of my projects. It's something like it is suggested at C++ FAQ Lite.
The neat thing is that you can use it like this:
int main()
{
Matrix m(10,10);
m(5,8) = 106.15;
std::cout << m(5,8);
...
}
Now, I have a graph composed of vertices and each vertex has a public (just for simplicity of the example) pointer to 2D matrix like above. Now I do have a pretty ugly syntax to access it.
(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...
Probably I'm missing some syntactic sugar here due to my inexperience with operator overloading. Is there a better solution?
Consider using references instead of pointers (provided, it can't be null and you can initialize in the constructor).
Consider making a getter or an instance of a matrix wrapper class for a vertex that returns a reference to 2D matrix (provided, it can't be null).
sampleVertex.some2DTable()(0,0) = 0;
sampleVertex.some2DTableWrap(0,0) = 0;
However, to me it sounds like a non-issue to justify going through all the trouble.
If you have a pointer to a Matrix, e.g. as a function parameter that you can't make a reference (legacy code, e.g.), you can still make a reference to it (pseudo code):
struct Matrix {
void operator () (int u, int v) {
}
};
int main () {
Matrix *m;
Matrix &r = *m;
r (1,1);
}
You're basically limited to (*sampleVertex.some2DTable)(0,0). Of course, if you don't need reseating, why not store the actual values in the matrix instead?
Alternatively, make the pointer private and make an accessor (note: the following examples assume a matrix of EntryTypes):
Matrix& Vertex::GetTableRef()
{
return *some2DTable;
}
// or
Matrix::EntryType& Vertex::GetTableEntry(int row, int col)
{
return (*some2DTable)(row,col);
}
// way later...
myVertex.GetTableRef()(0,0) = 0;
// or...
myVertex.GetTableEntry(0,0) = 0;
Or, just define an inline function to do this for you if you can't change the class Vertex:
// in some header file
inline Matrix& GetTableRef(Vertex& v)
{
return *v.some2DTable;
}
// or you could do this
inline Matrix::EntryType& GetTableEntry(Vertex& v, int row, int col)
{
return (*v.some2DTable)(row, col);
}
// later...
GetTableRef(myVertex)(0, 0) = 0;
// or
GetTableEntry(myVertex, 0, 0) = 0;
Finally, don't forget that you don't have to use operator overloading. STL collections implement an at() member function, which is checked, as opposed to operator[] which is unchecked. If you don't mind the overhead of bounds checking, or if you just want to be nonstandard, you could implement at() and then just call myVertex.some2DTable->at(0,0), saving a bit of a syntactic headache altogether.
There is no C++ syntactic sugar that will ease the pain of what you describe:
(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...
In this situation, I would either have the graph return a reference instead of a pointer, or have the matrix define a function which calls the operator():
inline matrixType &Matrix::get( int x, int y ){ return operator()(x,y); }
Then, the syntax isn't quite as ugly for the vertex example:
sampleVertex.some2DTable->get(0,0) = 0;
I would add a function that returns you a ref like rlbond recommends. For a quick fix or if you don't have control over the source of it, i would go with this:
sampleVertex.some2DTable[0](0,0) = 0; // more readable
That's actually equivalent, because the following holds if a is a pointer to a defined class:
*a == *(a + 0) == a[0]
See this long discussion on comp.lang.c++ about that same problem with good answers.
This is the best way without changing your code:
//some2DTable is a pointer to a matrix
(*sampleVertex.some2DTable)(0,0)
You could also instead make some2DTable a reference to a matrix instead of a pointer to a matrix. Then you would have simplified syntax as in your first code sniplet.
//some2DTable is a reference to a matrix instead of a pointer to a matrix
sampleVertex.some2DTable(0,0)
Or you could keep some2DTable a pointer to a reference and simply store a reference variable to it and use that in the context of your code block.
I'd change the way you get hold of "sampleVertex.some2DTable" so it returns a reference.
Either that or create the reference yourself:
Matrix& m = *sampleVertex.some2DTable;
m(1,2) = 3;
I don't know if it's worth the trouble, but you could do:
class MatrixAccessor {
private:
Matrix2D* m_Matrix;
public:
MatrixAccessor(Matrix2D* matrix) : m_matrix(matrix) { }
double& operator()(int i, int j) const { return (*m_Matrix)(i,j); }
Matrix2D* operator->() const { return m_Matrix; }
void operator=(Matrix2D* matrix) { m_Matrix = matrix; }
};
Provided the original operator() returns a reference (as it is in many matrix classes).
Then you provide that MatrixAccessor in your vertex class:
class Vertex {
Matrix2D* myMatrix;
public:
MatrixAccessor matrix;
Vertex(Matrix2D *theMatrix) : myMatrix(theMatrix), matrix(theMatrix) { }
};
Then you can write:
Vertex v;
v.matrix(1,0) = 13;
v.matrix->SomeOtherMatrixOperation();
EDIT
I added const keywords (thanks to #phresnel for bringing up the topic) in order to make the solution semantically equivalent to a solution only presenting a public Matrix2D-pointer.
An advantage of this solution is that constness could be transferred to the matrix object by adding two non-const versions of the operator()() and operator->() (i.e. the matrix cannot be modified on const vertices) and changing the const ones to return a const double& and const Matrix2D* respectively.
That would not be possible when using a public pointer to the matrix object.
You could implement Matrix::operator (int,int) by calling a member function and use that one directly when dealing with pointers.
class Matrix
{
public:
float ElementAt( int i, int j ) const { /*implement me*/ }
float operator() ( int i, int j ) const { return ElementAt( i, j ); }
...
};
void Foo(const Matix* const p)
{
float value = p->ElementAt( i, j );
...
}
void Bar(const Matrix& m)
{
float value = m(i,j);
}