Yes, this question has been asked before, but the problem was that the operator was a member function and that's not the case here. These are my files:
minmax.h
#ifndef MINMAX_H
#define MINMAX_H
class MinMax
{
private:
int m_nMin;
int m_nMax;
public:
MinMax(int nMin, int nMax);
int GetMin() { return m_nMin; }
int GetMax() { return m_nMax; }
friend MinMax operator+(const MinMax &cM1, const MinMax &cM2);
friend MinMax operator+(const MinMax &cM, int nValue);
friend MinMax operator+(int nValue, const MinMax &cM);
};
#endif // MINMAX_H
minmax.cpp
#include "minmax.h"
MinMax::MinMax(int nMin, int nMax)
{
m_nMin = nMin;
m_nMax = nMax;
}
MinMax MinMax::operator+(const MinMax &cM1, const MinMax &cM2)
{
//compare member variables to find minimum and maximum values between all 4
int nMin = cM1.m_nMin < cM2.m_nMin ? cM1.m_nMin : cM2.m_nMin;
int nMax = cM1.m_nMax > cM2.m_nMax ? cM1.m_nMax : cM2.m_nMax;
//return a new MinMax object with above values
return MinMax(nMin, nMax);
}
MinMax MinMax::operator+(const MinMax &cM, int nValue)
{
//compare member variables with integer value
//to see if integer value is less or greater than any of them
int nMin = cM.m_nMin < nValue ? cM.m_nMin : nValue;
int nMax = cM.m_nMax > nValue ? cM.m_nMax : nValue;
return MinMax(nMin, nMax);
}
MinMax MinMax::operator+(int nValue, const MinMax %cM)
{
//switch argument places and pass them to previous operator version
//this avoids duplicate code by reusing function
return (cM + nValue);
}
main.cpp
#include <iostream>
#include "minmax.h"
using namespace std;
int main()
{
MinMax cM1(10, 15);
MinMax cM2(8, 11);
MinMax cM3(3, 12);
//sum all MinMax objects to find min and max values between all of them
MinMax cMFinal = cM1 + 5 + 8 + cM2 + cM3 + 16;
cout << cMFinal.GetMin() << ", " << cMFinal.GetMax() << endl;
return 0;
}
The message reads error: 'MinMax MinMax::operator+(const MinMax&, const MinMax&)' must take either zero or one argument
To turn my comment into an answer:
You're defining your function as a member function by putting MinMax:: in front of it, so they are member functions.
MinMax MinMax::operator+(const MinMax &cM, int nValue)
{ // should be operator+ without the MinMax:: at the front.
//compare member variables with integer value
//to see if integer value is less or greater than any of them
int nMin = cM.m_nMin < nValue ? cM.m_nMin : nValue;
int nMax = cM.m_nMax > nValue ? cM.m_nMax : nValue;
return MinMax(nMin, nMax);
}
you can see it working here
As you've said, they are not member functions.
Therefore, in their definitions, the MinMax:: prefix is incorrect and should not be there.
Related
Similar Question is available here: How do I sort a vector of pairs based on the second element of the pair? but I am interested in External Memory Sorting.
I have tried using the analogies from Internal Memory Sorting but the error occurs in sorter_stream.h file of STXXL as:
My code :
#include <iostream>
#include <stxxl/vector>
#include <stxxl/sorter>
#include <limits>
using namespace std;
typedef std::pair<int,int> my_pair;
struct my_comparator
{
bool operator()(const my_pair& left, const my_pair& right)
{
return left.first < right.first;
}
int min_value() const
{
return std::numeric_limits<int>::min();
}
int max_value() const
{
return std::numeric_limits<int>::max();
}
};
int main()
{
typedef stxxl::sorter<my_pair, my_comparator> sorter_type;
sorter_type int_sorter(my_comparator(), 64 * 1024 * 1024);
for (int i = 10; i > 0; i--)
{
int_sorter.push(my_pair(i,i+10));
}
int_sorter.sort(); // sort elements (in ascending order)
while (!int_sorter.empty())
{
std::cout << (*int_sorter).first << " "<<(*int_sorter).second<<endl;
++int_sorter;
}
return 0;
}
Error :
sort_stream.h(481): error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
UPDATE:
Changing the return type of min_value(),max_value() function to my_pair as:
struct my_comparator
{
bool operator()(const my_pair& left, const my_pair& right)
{
return left.first < right.first;
}
my_pair min_value() const
{
return my_pair(std::numeric_limits<int>::min(),std::numeric_limits<int>::min());
}
my_pair max_value() const
{
return my_pair(std::numeric_limits<int>::max(),std::numeric_limits<int>::max());
}
};
gives the following Error:
sort_helper.h(94): error C3848: expression having type 'const my_comparator' would lose some const-volatile qualifiers in order to call 'bool my_comparator::operator ()(const my_pair &,const my_pair &)'
P.S. : Being a novice (Reputation<50) , I am not allowed to comment, that's why writing a new Question.
Got the following example in STXXL:Sorter Section which addresses the same problem.
Code:
#include <stxxl/sorter>
#include <stxxl/stats>
#include <stxxl/timer>
#include <stxxl/random>
#include <limits>
struct TwoInteger
{
int i, j;
TwoInteger()
{ }
TwoInteger(int _i, int _j)
: i(_i), j(_j)
{ }
};
struct TwoIntegerComparator
{
bool operator () (const TwoInteger& a, const TwoInteger& b) const
{
return a.i < b.i;
}
TwoInteger min_value() const
{
return TwoInteger(std::numeric_limits<int>::min(), std::numeric_limits<int>::min());
}
TwoInteger max_value() const
{
return TwoInteger(std::numeric_limits<int>::max(), std::numeric_limits<int>::max());
}
};
int main()
{
// template parameter <ValueType, CompareType, BlockSize(optional), AllocStr(optional)>
typedef stxxl::sorter<TwoInteger, TwoIntegerComparator, 1*1024*1024> sorter_type;
// create sorter object (CompareType(), MainMemoryLimit)
sorter_type int_sorter(TwoIntegerComparator(), 64 * 1024 * 1024);
stxxl::random_number32 rand32;
stxxl::timer Timer1;
Timer1.start();
// insert random numbers from [0,100000)
for (size_t i = 0; i < 1000; ++i)
{
int_sorter.push(TwoInteger(rand32() % 100000, (int)i)); // fill sorter container
}
Timer1.stop();
STXXL_MSG("push time: " << (Timer1.mseconds() / 1000));
stxxl::timer Timer2;
Timer2.start();
int_sorter.sort(); // switch to output state and sort
Timer2.stop();
STXXL_MSG("sort time: " << (Timer2.mseconds() / 1000));
// echo sorted elements
while (!int_sorter.empty())
{
std::cout << int_sorter->i << " "; // access value
++int_sorter;
}
return 0;
}
I'm curently learning about operator overloading and I found this example:
#include <iostream>
using namespace std;
class MinMax
{
private:
int m_nMin; // The min value seen so far
int m_nMax; // The max value seen so far
public:
MinMax(int nMin, int nMax)
{
m_nMin = nMin;
m_nMax = nMax;
}
int GetMin() { return m_nMin; }
int GetMax() { return m_nMax; }
friend MinMax operator+(const MinMax &cM1, const MinMax &cM2);
friend MinMax operator+(const MinMax &cM, int nValue);
friend MinMax operator+(int nValue, const MinMax &cM);
};
MinMax operator+(const MinMax &cM1, const MinMax &cM2)
{
// Get the minimum value seen in cM1 and cM2
int nMin = cM1.m_nMin < cM2.m_nMin ? cM1.m_nMin : cM2.m_nMin;
// Get the maximum value seen in cM1 and cM2
int nMax = cM1.m_nMax > cM2.m_nMax ? cM1.m_nMax : cM2.m_nMax;
return MinMax(nMin, nMax);
}
MinMax operator+(const MinMax &cM, int nValue)
{
// Get the minimum value seen in cM and nValue
int nMin = cM.m_nMin < nValue ? cM.m_nMin : nValue;
// Get the maximum value seen in cM and nValue
int nMax = cM.m_nMax > nValue ? cM.m_nMax : nValue;
return MinMax(nMin, nMax);
}
MinMax operator+(int nValue, const MinMax &cM)
{
// call operator+(MinMax, nValue)
return (cM + nValue);
}
int main()
{
MinMax cM1(10, 15);
MinMax cM2(8, 11);
MinMax cM3(3, 12);
MinMax cMFinal = cM1 + cM2 + 5 + 8 + cM3 + 16;
cout << "Result: (" << cMFinal.GetMin() << ", " <<
cMFinal.GetMax() << ")" << endl;
return 0;
}
I don't understand how does the line MinMax cMFinal = cM1 + cM2 + 5 + 8 + cM3 + 16; work.
When this is calculated it becomes MinMax cMFinal = MinMax(3, 16). What happenes next? How does the compiler assign one object to another when I didn't define overloading assigment operator?
Lets say you have two MinMax objects, a and b. Then when you have a line like
MinMax c = a + b;
Then the compiler translates it to the following
MinMax c = operator+(a, b);
In other words, it's like a normal function call.
If you do multiple operations, like
MinMax d = a + b + c;
then the compiler will internally generate temporary variables and use, like
MinMax compilerGeneratedTemporary = operator+(a, b);
MinMax d = operator+(compilerGeneratedTemporary, c);
If it's the initialization you're wondering about, then it's calling the MinMax copy-constructor. When you declare and initialize an object variable at the same time then it's not an assignment, it just reuses the assignment operator.
The operator+ functions return a MinMax object, which is passed to the class copy-constructor.
If a class doesn't have a copy-constructor, the compiler will generate one for you automatically (with a few exceptions, see the reference linked below).
Read more about the copy-constructor here.
So I am working on "TEMPLATES" and I'm required to make a 3 attempt of a function called PrintMax -it's obvious what it does-, to print the maximum element in an array of 3 elements, each attempt is for a different data type in this array -double/int/complex-. So I'm required to first, create the class Complex, and its required operator overloads, after that I use the PrintMax function as template function to work on the 3 types of arrays.
The problem here lies within the 3rd array of course, I can't write the elements of Complex into the array in this for ( a + bi ), because this is my class Complex :
class Complex
{
private :
int imaginary;
int real;
public:
Complex (int = 0, int = 0);
~Complex ();
int getImaginary();
int getReal();
void setImagniary(int i);
void setReal (int r);
bool operator > (Complex&);
};
You can notice, I overloaded operator > to check, but I also have a little problem besides not being able to write the elements in that way, the second problem is I can't -or sleepy and my brain is dying- calculate which is maximum in this array of Complex numbers :
// Input: Complex Array
// 1+3i, 2+4i, 3+3i
// Expected Output: 2+4i
So I want to assign them in the array with this form : Arr[3] = {1+3i, 2+4i, 3+3i};
Why is that the expected output, why not 3+3i ?
Thanks for reading ~
It seems to me that you are looking for something like:
template <typename T> void PrintMax(T array[])
{
// It is assumed that array has 3 elements in it.
std::cout <<
array[0] > array[1] ?
(array[0] > array[2] ? array[0] : array[2]) :
(array[1] > array[2] ? array[1] : array[2])
std::endl;
}
You could use something like the following. Note that there are no range checks in the code, it is just to demonstrate a way how you could solve your problem.
Plus i would suggest you to use a container (eg. std::vector) instead of plain arrays.
#include <algorithm>
#include <cmath>
#include <iostream>
class Complex {
private:
int imaginary;
int real;
public:
Complex(int r, int i) :
imaginary(i), real(r) {
}
~Complex() {
}
int getImaginary() const {
return imaginary;
}
int getReal() const {
return real;
}
void setImaginary(int i) {
imaginary = i;
}
void setReal(int r) {
real = r;
}
double getAbsolut() const {
return std::abs(std::sqrt(std::pow(imaginary, 2) + std::pow(real, 2)));
}
friend bool operator<(const Complex& lhs, const Complex& rhs);
friend std::ostream& operator<<(std::ostream& stream,
const Complex& complex);
};
bool operator<(const Complex& lhs, const Complex& rhs) {
return lhs.getAbsolut() < rhs.getAbsolut();
}
std::ostream& operator<<(std::ostream& stream, const Complex& complex) {
stream << "Complex(" << complex.real << "+" << complex.imaginary
<< "i)";
return stream;
}
template<int size, class T>
void getMax(const T arr[]) {
T max_value = arr[0];
for (size_t i = 1; i < size; ++i) {
max_value = std::max(max_value, arr[i]);
}
std::cout << "max: " << max_value << std::endl;
}
int main(int argc, char **argv) {
Complex arr_complex[] = { Complex(3, 3), Complex(2, 4), Complex(1, 3) };
int arr_int[] = { 3, 5, 1 };
double arr_double[] = { 2.3, 5.6, 9.1 };
getMax<3>(arr_complex);
getMax<3>(arr_int);
getMax<3>(arr_double);
return 0;
}
The idea is to overload an operator * so it can multiply two strings representing decimal value of a number. The operator is part of a bigger class but that is not important. The algorithm is the same as in elementary school :)
Here's my code:
Bignumber operator* (Bignumber x, Bignumber y ){
int i, j, transfer=0, tmp, s1, s2, k;
char add[1];
string sol;
string a, b;
Bignumber v1, v2;
a=x.GetValue();
b=y.GetValue();
a.insert(0,"0");
b.insert(0,"0");
for(i=a.length()-1; i>=0; i--){
s1 = (int) a[i]-48;
for(k=a.length()-i-1; k >0 ; k--){
sol+="0";
}
for(j=b.length()-1; j >=0; j--){
s2=(int) b[j]-48;
tmp=s1*s2+transfer;
if(tmp >= 10){
transfer=tmp/10;
tmp=tmp-(10*transfer);
}
itoa(tmp, add, 10);
sol.insert(0, add);
}
v1=sol;
v2=v1+v2;
sol.erase(0);
transfer=0;
}
return v2;
}
This works fine most of the time but for some random values it doesnt work properly. like for example for 128*28 it returns 4854 instead of 3584.
Any idea what might be the problem?
operators + and = are already overloaded for the class Bignumber and they work fine.
While my first answer solves your issue (by my testing, anyway), here's an alternative implementation; I don't have your Bignumber class so I wrote a small fake one to test with:
#include <string>
#include <ios>
#include <iostream>
#include <ostream>
#include <sstream>
class Bignumber
{
static inline unsigned long long strtoull(std::string const& str)
{
unsigned long long val;
return std::istringstream(str) >> val ? val : 0uLL;
}
unsigned long long val_;
public:
Bignumber() : val_() { }
explicit Bignumber(unsigned long long const val) : val_(val) { }
explicit Bignumber(std::string const& str) : val_(strtoull(str)) { }
Bignumber& operator +=(Bignumber const rhs)
{
val_ += rhs.val_;
return *this;
}
std::string GetValue() const
{
std::ostringstream oss;
oss << val_;
return oss.str();
}
};
Bignumber operator *(Bignumber const x, Bignumber const y)
{
typedef std::string::const_reverse_iterator cr_iter_t;
std::string const& a = '0' + x.GetValue();
std::string const& b = '0' + y.GetValue();
Bignumber ret;
for (cr_iter_t a_iter = a.rbegin(), a_iter_end = a.rend(); a_iter != a_iter_end; ++a_iter)
{
unsigned transfer = 0u;
std::string sol(a.end() - a_iter.base(), '0');
for (cr_iter_t b_iter = b.rbegin(), b_iter_end = b.rend(); b_iter != b_iter_end; ++b_iter)
{
unsigned tmp = static_cast<unsigned>(*a_iter - '0') * static_cast<unsigned>(*b_iter - '0') + transfer;
if (tmp >= 10u)
{
transfer = tmp / 10u;
tmp -= transfer * 10u;
}
sol.insert(sol.begin(), static_cast<char>(tmp + '0'));
}
ret += Bignumber(sol);
}
return ret;
}
int main()
{
Bignumber const z = Bignumber(123456789uLL) * Bignumber(987654321uLL);
std::cout << std::boolalpha << (z.GetValue() == "121932631112635269") << std::endl;
}
itoa null-terminates the string it writes, so add is too small for the data being written to it, resulting in memory corruption. Change the definition of add to char add[2]; and it should work.
I would like to know if it is possible to create an actual functor object from a lambda expression. I don't think so, but if not, why?
To illustrate, given the code below, which sorts points using various policies for x and y coordinates:
#include <vector>
#include <functional>
#include <algorithm>
#include <iostream>
struct Point
{
Point(int x, int y) : x(x), y(y) {}
int x, y;
};
template <class XOrder, class YOrder>
struct SortXY :
std::binary_function<const Point&, const Point&, bool>
{
bool operator()(const Point& lhs, const Point& rhs) const
{
if (XOrder()(lhs.x, rhs.x))
return true;
else if (XOrder()(rhs.x, lhs.x))
return false;
else
return YOrder()(lhs.y, rhs.y);
}
};
struct Ascending { bool operator()(int l, int r) const { return l<r; } };
struct Descending { bool operator()(int l, int r) const { return l>r; } };
int main()
{
// fill vector with data
std::vector<Point> pts;
pts.push_back(Point(10, 20));
pts.push_back(Point(20, 5));
pts.push_back(Point( 5, 0));
pts.push_back(Point(10, 30));
// sort array
std::sort(pts.begin(), pts.end(), SortXY<Descending, Ascending>());
// dump content
std::for_each(pts.begin(), pts.end(),
[](const Point& p)
{
std::cout << p.x << "," << p.y << "\n";
});
}
The expression std::sort(pts.begin(), pts.end(), SortXY<Descending, Ascending>()); sorts according to descending x values, and then to ascending y values. It's easily understandable, and I'm not sure I really want to make use of lambda expressions here.
But if I wanted to replace Ascending / Descending by lambda expressions, how would you do it? The following isn't valid:
std::sort(pts.begin(), pts.end(), SortXY<
[](int l, int r) { return l>r; },
[](int l, int r) { return l<r; }
>());
This problem arises because SortXY only takes types, whereas lambdas are objects. You need to re-write it so that it takes objects, not just types. This is basic use of functional objects- see how std::for_each doesn't take a type, it takes an object.
I have posted a similar question w.r.t. lambda functors within classes.
Check this out, perhaps it helps:
Lambda expression as member functors in a class
I had a similar problem: It was required to provide in some cases a "raw"-function pointer and in other a functor. So I came up with a "workaround" like this:
template<class T>
class Selector
{
public:
Selector(int (*theSelector)(T& l, T& r))
: selector(theSelector) {}
virtual int operator()(T& l, T& r) {
return selector(l, r);
}
int (*getRawSelector() const)(T&, T&) {
return this->selector;
}
private:
int(*selector)(T& l, T& r);
};
Assuming you have two very simple functions taking --- as described --- either a functor or a raw function pointer like this:
int
findMinWithFunctor(int* array, int size, Selector<int> selector)
{
if (array && size > 0) {
int min = array[0];
for (int i = 0; i < size; i++) {
if (selector(array[i], min) < 0) {
min = array[i];
}
}
return min;
}
return -1;
}
int
findMinWithFunctionPointer(int* array, int size, int(*selector)(int&, int&))
{
if (array && size > 0) {
int min = array[0];
for (int i = 0; i < size; i++) {
if (selector(array[i], min) < 0) {
min = array[i];
}
}
return min;
}
return -1;
}
Then you would call this functions like this:
int numbers[3] = { 4, 2, 99 };
cout << "The min with functor is:" << findMinWithFunctor(numbers, 3, Selector<int>([](int& l, int& r) -> int {return (l > r ? 1 : (r > l ? -1 : 0)); })) << endl;
// or with the plain version
cout << "The min with raw fn-pointer is:" << findMinWithFunctionPointer(numbers, 3, Selector<int>([](int& l, int& r) -> int {return (l > r ? 1 : (r > l ? -1 : 0)); }).getRawSelector()) << endl;
Of course in this example there is no real benefit passing the int's as reference...it's just an example :-)
Improvements:
You can also modify the Selector class to be more concise like this:
template<class T>
class Selector
{
public:
typedef int(*selector_fn)(T& l, T& r);
Selector(selector_fn theSelector)
: selector(theSelector) {}
virtual int operator()(T& l, T& r) {
return selector(l, r);
}
selector_fn getRawSelector() {
return this->selector;
}
private:
selector_fn selector;
};
Here we are taking advantage of a simple typedef in order to define the function pointer once and use only it's name rather then writing the declaration over and over.