I have a class and i overloaded [ operator to use in main. But the problem here is; somewhere in the class in another function. i want to use [ operator like the old style. How can i use them both or how can i modify my overloaded [ parameter ?
Here is overloading part.
T &operator[](int i)
{
if (i < 0 || i >= ArithmeticVector<T>::size())
throw std::string("Out of bounds!"); //throw std::out_of_range;
else
return data[i];
};
And here is another function i want to use;
friend ArithmeticVector<T> operator /(const ArithmeticVector<T>& v1, const ArithmeticVector<T>& v2 )
{
/*Do quick size check on vectors before proceeding*/
ArithmeticVector<T> result(v1.size());
for (unsigned int i = 0; i < result.size(); ++i)
{
result[i]=v1[i]/v2[i];
}
return result;
};
I get an error like error C2678: binary '[' : no operator found which takes a left-hand operand of type 'const ArithmeticVector'
The problem is with this line.
result[i]=v1[i]/v2[i];
overloaded operator didn't like it :/
I can't understand, what do you mean by I want to use [] operator like the old style, but you should overload operator[] for const version too:
const T& operator[](int i) const
{
// ...
}
v1 and v2 non-modifiable here, they can't call non-const methods.
You need to overload the access operator for const objects as well, because the r.h.s of the expression result[i] = v1[1] / v2 [i] will evaluate to:
v1.operator[](i) / v2.operator[](i)
and both v1 and v2 are of type const ArithmeticVector<T>& which means that the compiler will try to find the operator[](int) const for both of them (they are constant objects). When you overload the operator for const as advised in the answer above, you can re-use the code in the const operator and just call the operator in the non-const operator by casting away constness of the object. That way you don't have to think about what you implemented in one operator and port it to another, and you don't have to debug your code at two places. Here is the model of your problem (I don't have your implementation of ArithmeticVector, so you have to use the parts of it for your stuff):
template<typename T>
class ArithmeticVector;
template<typename T>
ArithmeticVector<T> operator / (
const ArithmeticVector<T>& v1,
const ArithmeticVector<T>& v2
);
template<typename T>
class ArithmeticVector
{
public:
// Your declaration
T& operator[](int i)
{
// Casting away constness allows code re-use.
return const_cast<ArithmeticVector&>(*this).operator[](i);
}
// Const declaration:
T& operator[](int i) const
{
// Put your operator code here.
}
friend ArithmeticVector<T> operator / <> (
const ArithmeticVector<T>& v1,
const ArithmeticVector<T>& v2
);
};
template<typename T>
ArithmeticVector<T> operator / (
const ArithmeticVector<T>& v1,
const ArithmeticVector<T>& v2
)
{
//ArithmeticVector<T> result(v1.size());
ArithmeticVector<T> result;
result[0]=v1[0]/v2[0];
return result;
};
int main(int argc, const char *argv[])
{
ArithmeticVector<int> v1, v2, v3;
v1 = v2 / v3;
return 0;
}
There is a great book of Scott Meyers "Effective C++" and there you can read a great description on constness of objects and access operators. There is an answer on SO, that talks about this.
You need to also take care to avoid a Floating Point Exception (division by zero), or SIGFPE, which will happen when v3[i] == 0, which you can do either by stabilizing the result (you loose accuracy):
result[i] = v1[i] / (v2[I] + 1e-15)
or you introduce a test which slows down the divison significantly (like an if testing if v2[i] == 0).
Related
I would like to overload operator[] to accept 2 int's, so that the user will be able to specify a range of indices like so:
MyClass[1:5]
I tried this:
void operator[](const int, const int);
with the hope that I would be able to use it with comma:
MyClass[1,5]
but I get a compiler error:
too many parameters for this operator function
Is there a way that I can achieve such behaviour?
Thanks
EDIT:
I was hoping the operator would do something like so:
struct MyClass
{
vector<std::string> data;
void operator[] (const int start, const int end)
{
for(int index = start; index <= end; index++)
{
cout << data[index] << '\n';
}
}
};
It's impossible.
You need to pick a different syntax, e.g:
MyClass(1,5) - overloaded operator().
MyClass.foo(1,5) - a member function.
MyClass[{1,5}] - overloaded operator[] with a parameter of class type, which has a constructor that accepts 2 parameters.
You can use for example std::initializer_list as an argument.
For example
T & operator []( const std::initializer_list<size_t> & );
const T & operator []( const std::initializer_list<size_t> & ) const;
or just like
T operator []( const std::initializer_list<size_t> & ) const;
class Star {
public:
// The distance between this star to the Earth.
double distance() const { return sqrt(x_ * x_ + y_ * y_ + z_ * z_); }
bool operator<(const Star& s) const { return distance() < s.distance(); }
int ID_;
double x_, y_, z_;
};
priority_queue<Star, vector<Star>> max_heap;
Look at last line. This is priority_queue max_heap's initialization. Why it ignore the c++ const Compare&.
I thought it would be
priority_queue<Star, vector<Star>, Star> max_heap;
It looks different as below one, which I understand.
class mycomparison
{
bool reverse;
public:
mycomparison(const bool& revparam=false)
{reverse=revparam;}
bool operator() (const int& lhs, const int&rhs) const
{
if (reverse) return (lhs>rhs);
else return (lhs<rhs);
}
};
int main ()
{
int myints[]= {10,60,50,20};
std::priority_queue<int> first;
std::priority_queue<int> second (myints,myints+4);
std::priority_queue<int, std::vector<int>, std::greater<int> >
third (myints,myints+4);
// using mycomparison:
typedef std::priority_queue<int,std::vector<int>,mycomparison> mypq_type;
mypq_type fourth; // less-than comparison
mypq_type fifth (mycomparison(true)); // greater-than comparison
return 0;
}
I read this page:
http://www.cplusplus.com/reference/queue/priority_queue/priority_queue/
cannot get the definitive definition of priority_queue constructor paradigm.
Also, Why sometimes it overloads "<" as comparator. Sometimes overloads "()" as comparator?
thanks
The default comparison is std::less< Star > which will call the operator < you have defined.
Template type parameters can have deault arguments, just like function parameters. It's the same with the default container type, which is std::vector< Star >. Actually you can write the declaration simply as
priority_queue<Star> max_heap;
Also, Why sometimes it overloads "<" as comparator. Sometimes overloads "()" as comparator?
The comparator is always a Callable object, that is, a function or function-like object (functor). The things to be compared are passed using function-call notation with parentheses. std::less is the adaptor which makes a given bool operator< (T, T) overload accessible as the member operator() of a functor.
For example, here is how std::less may be implemented:
template< typename T >
struct less {
bool operator () ( T const & lhs, T const & rhs ) const
{ return lhs < rhs; } // Calls Star::operator < ()
};
std::less is actually an object type, and such an object is actually stored inside the priority_queue. Its operator() is what makes the comparison. The call to your operator < happens this way.
So for class this week I have to use a set to read in the Declaration of Independence and the US Constitution from a .txt file, store them in sets, and overload operator* to find and return the intersection of the two sets.
Reading everything in is not a problem, neither is finding out the intersection in the sets. What I'm having a lot of trouble with is overloading operator*. I keep getting two errors:
no operator "*" matches these operands
and
binary "*":'std::set<_Kty>' does not define this operator or a conversion to a type acceptable to the predefined operator
Here is my code so far:
From main:
Reader r;
std::set<std::string> d, c;
d = r.GetDeclaraton();
c = r.GetConstitution();
Set dec(d), con(c);
Set intersection = dec * con;
The errors are coming from that last line of main.
From Set.h
class Set
{
public:
std::set<std::string> s;
Set(void);
Set(std::set<std::string> set)
{
s = set;
}
~Set(void);
std::set<std::string> operator* (const std::set<std::string> &rhs)
{
std::set<std::string> newset;
std::set<std::string>::iterator rhsiter = rhs.begin(), result;
while (rhsiter != rhs.end())
{
result = s.find(*rhsiter++);
if (result != rhs.end())
{
newset.insert(*result);
}
}
return newset;
}
};
You need
Set operator* (const Set &rhs) const
because this is a binary operator with two Sets as arguments. Your attempt would only work if your Set was deriving std::set.
The return type here is Set. It makes more sense to be the same as the input arguments, and this is also consistent with your usage in main. So in this case you need to modify the definition to construct and return a Set instead of an std::set (or rather you need not because an std::set can be implicitly converted to a Set).
Note also I made operator* a const member function, since it's not modifying its object.
operator* is defined in your custom Set so the left-hand-side argument must be a Set, but in dec.s * con.s you're using .s which accesses the member std::set fields, and there's no operator* defined for a left-hand Set and rhs-hand std::set.
You could change to dec * con.s, but it'd be better to change the operator* rhs argument to a const Set& too, and use rhs.s inside the operator... less confusing!
In my opinion its better to write a global or friend operator. Also, for intersection I would use the & operator, for union the | or + operator while, difference: -...
Why global operators? With global operators you can write an operator for your class even if the left operand is not your class. For example in case of a matrix class you can easily write a global operator that multiplies together a float and a matrix while as a matrix member operator you could write only an operator where your matrix is on the left.
Example:
template <typename T>
inline std::set<T> intersection(const std::set<T>& smaller, const std::set<T>& larger)
{
std::set<T> result;
for (auto it=smaller.begin(),eit=smaller.end(); it!=eit; ++it)
{
if (larger.find(*it) != larger.end())
result.insert(*it);
}
return result;
}
template <typename T>
inline std::set<T> operator & (const std::set<T>& a, const std::set<T>& b)
{
if (a.size() < b.size())
return intersection(a, b);
return intersection(b, a);
}
class Set
{
public:
std::set<std::string> s;
Set() {}
Set(std::set<std::string> _s) : s(_s) {}
friend Set operator & (const Set& a, const Set& b)
{
return Set(a.s & b.s);
}
};
int test()
{
std::set<std::string> s, t;
s.insert("aa");
s.insert("bb");
t.insert("bb");
t.insert("cc");
std::set<std::string> u(s & t);
Set ss(s), st(t);
Set result(ss & st);
return 0;
}
i have
class c1{
public:
int number;
c1()
{
number=rand()%10;
}
bool operator < (c1 *w)
{
return number < w->number;
}
};
vector<c1*> vec = { ... }
sort(vec.begin(),vec.end())
why it dosent sort ?
but if we had
bool operator < (c1 w)
{
return number < w.number;
}
and
vector<c1> vec = { ... }
it would have been sorted !
The most straightforward approach is to define a function
bool c1_ptr_less( c1 const *lhs, c1 const *rhs ) {
return lhs->something < rhs->something;
}
std::sort( vec.begin(), vec.end(), & c1_ptr_less );
What I would suggest is a generic functor to take care of all pointer arrays
struct pointer_less {
template< typename T >
bool operator()( T const *lhs, T const *rhs ) const
{ return * lhs < * rhs; }
};
std::sort( vec.begin(), vec.end(), pointer_less() );
Armed with this, define the usual c1::operator< ( const c1 & ) and likewise for other classes.
Generally, best practice is to avoid pointers entirely, including arrays of pointers.
To answer your title question, you can't.
Pointers are built-in types, you cannot override operators where all operands are built-in types.
Luckily, there's an overload of std::sort that allows you to specify a comparison function (or functor) so the operator< isn't used.
bool operator < (c1 *w) compares a c1 to a c1 * - Your sort compares a c1 * to a c1 *
You need to pass a compare function to std::sort:
bool compare_c1 (c1* x, c1* y)
{
return *x < y;
}
std::sort(v.begin(), v.end(), compare_c1);
Or if you are using GCC >= 4.5 or Visual Studio 2010 (I'm do not know sure about Intel compiler) you can use lambdas (they are part of the C++0x standard):
std::sort(v.begin(), v.end(), [] (c1* x, c1* y) { return *x < y; });
Add a external operator< and keep de original one:
bool operator<(c1* a, c1* b) { return *a < *b; }
Now sort will work on the vector.
phimuemue's answer sums it up, I'll just add that, as a workaround, you can create a wrapper class that contains only one member - a pointer to c1, and then overload its operator <. Then you could sort a vector of object of that class.
And in your example, vector<c1*> is sorted. Just not to the
criteria you seem to want: by default, sort uses
std::less<T> as the ordering criteria, and std::less<ci*>
compares the pointers (which is what you'd expect). If you
don't want the default criteria, then you have to pass a third
argument to sort, a predicate defining the ordering you want.
And of course, your member operator<(c1*) will only be called
when you compare a c1 with a ci* (and only if the c1 is an
rvalue). Such operators are very, very rare---normally, both
sides of a < operator should take the same type (and should be
const, since a < operator which modifies the values of the
objects it compares would be surprising, to say the least).
I'm trying to create an overridden operator function using both const parameters, but I can't figure out how to do it. Here is a simple example:
class Number
{
Number()
{
value = 1;
};
inline Number operator + (const Number& n)
{
Number result;
result.value = value + n.value;
return result;
}
int value;
}
What I am trying to do here is pass in two arguments into the addition function that are both const and return the result without changing anything in the class:
const Number a = Number();
const Number b = Number();
Number c = a + b;
Is this possible and how would I go about doing this?
Thanks,
Dan
inline is understood in class declarations so you don't need to specify it.
Most idiomatically, you would make operator+ a non-member function declared outside the class definition, like this:
Number operator+( const Number& left, const Number& right );
You might need to make it a friend of the class if it needs access to Number's internals.
If you have to have it as a member function then you need to make the function itself const:
Number operator+( const Number& n ) const
{ // ...
For classes like Number, operator+ is typically implemented in terms of operator+= as usually you want all the usual operators to work as expected and operator+= is typically easier to implement and operator+ tends not to lose any efficiency over implementing it separately.
Inside the class:
Number& operator+=( const Number& n );
Outside the class:
Number operator+( const Number& left, const Number& right )
{
return Number( left ) += right;
}
or even:
Number operator+( Number left, const Number& right )
{
return left += right;
}
class Number
{
Number()
{
value = 1;
};
inline Number operator + (const Number& n) const
{
Number result;
result = value + n.value;
return result;
}
int value;
}
How about:
inline Number operator + (const Number& n) const
While I feel the previous answers are good enough, I believe some clarification is needed.
Operators come (usually) in two flavors
The first being the non-member functions, the second being the member function whose parameter is the "right operand" of the operation and which usually returns the current modified object.
For example, imagine there's an operator § for a class T. It could be written either as a non-member function:
T operator § (const T & lhs, const T & rhs)
{
T result ;
// do the lhs § rhs operation, and puts the result into "result"
return result ;
}
or as a member function:
T & T::operator § (const T & rhs)
{
// do the "this § rhs" operation, and puts the result into "this"
return *this ;
}
or even (very unusually) as another member function:
T T::operator § (const T & rhs) const
{
T result ;
// do the "this § rhs" operation, and puts the result into "result"
return result ;
}
Usually, you should prefer the non-member function, if only because you should not declare it friend. Thus, using non-member non-friend function enhance the encapsulation of your object.
Disclaimer: There are other flavors, but I'm limiting myself to arithmetic operators like +, *, /, -, etc. here, as well as "credible" operator prototypes.
Analyse your use of the operator
In the case of +:
Each operand needs to be constant because a = b + c must not change b, nor c.
You can accumulate +, like in a = b + c + d + e, so temporaries must exist.
T operator § (const T & lhs, const T & rhs)
{
T result ;
// do the lhs § rhs operation, and puts the result into "result"
return result ;
}
In the case of +=:
You know the left operand A (from A += B) will be modified.
You know the left operand A (from A += B) is its own result.
So you should use:
T & T::operator += (const T & rhs)
{
// do the "this § rhs" operation, and puts the result into "this"
return *this ;
}
As always, premature optimization is the root of all evil
I've seen this kind of code in production code so, it does happen:
T & operator + (const T & lhs, const T & rhs)
{
static T result ; // result is STATIC !!!!
// do the lhs + rhs operation, and puts the result into "result"
return result ;
}
The author hoped to economize one temporary. With this kind of code, writing a = b + c + d leads to interesting (and wrong) results.
^_^
Last but not least
I did write a list of operator overloading prototypes on this page. The page is still under construction, but its main use (easy to copy/paste working prototypes) can be quite useful...