L-value interpretation of overloading operator() - c++

While studying graph theory, I wanted to try some code, so I came up with this:
class edge
{
public:
edge(char v1, char v2, int wt = INT_MAX) : vertex1(v1), vertex2(v2), weight(wt) {}
edge(const edge& e)
{
this->vertex1 = e.vertex1;
this->vertex2 = e.vertex2;
this->weight = e.weight;
}
edge& operator=(const edge& e)
{
this->weight = e.weight;
return *this;
}
edge& operator=(const int& w)
{
this->weight = w;
return *this;
}
bool operator==(const edge& e) const
{
const auto res = this->weight == e.weight;
return res;
}
bool is_connected() const { return !(weight == INT_MAX); }
char vertex1;
char vertex2;
int weight;
};
And corresponding graph class:
class graph
{
public:
edge operator ()(const char &i, const char &j) const; // #1
edge& operator ()(const char &i, const char &j); // #2
// More implementations...
private:
std::vector<char> vertices;
std::vector<edge> edges;
};
This allows me to write code like this:
graph g;
g('a', 'b') = 1;
g('a', 'f') = 2;
g('a', 'b') = g('a', 'f'); // #2 is called
g('a', 'b'); // #2 is called
How can I cause #1 to get called? Okay, also it occurs to me that something might be wrong with this construct. Could someone kindly review this code for me? Thanks!
Also, I read this one here, but I need more information.

Overload resolution between these two methods is roughly equivalent to the overload resolution of the following two functions.
edge func(const graph *thiz, const char &i, const char &j); // #1
edge& func(graph *thiz, const char &i, const char &j); // #2
then the following call is fully matched with the #2 because the first argument is not const.
graph g;
func(&g, 'a', 'b');
However if the first argument was const, only #1 can be called.

If you want to do this sort of thing, you need to have your operator() return an edge_ref helper object that can be assigned to (to insert an edge into the graph), or implicitly converted into an edge:
class graph {
std::set<char> vertices;
std::map<std::pair<char, char>, int> edges;
class edge_ref {
graph &self;
char i, j;
public:
edge_ref(graph &g, char i, char j): self(g), i(i), j(j) {}
int operator=(int weight) {
self.vertices.insert(i);
self.vertices.insert(j);
return self.edges[std::make_pair(i, j)] = weight; }
operator int() {
return self.edges.at(std::make_pair(i, j)); }
};
public:
edge_ref operator()(char i, char j) { return edge_ref(*this, i, j); }

Related

Iterator gives different results based on usage c++

I recently started c++ programming. I shifted from Java.
I was building my own Iterable class template like this:
template<class T> class Iterable
{
T start,stop;
public:
explicit Iterable(T s,T e) {start=s; stop=e;;}
public:
virtual void next(T& i) =0;
public:
class iterator: public std::iterator<
std::input_iterator_tag, // iterator_category
T, // value_type
long, // difference_type
const T*, // pointer
T // reference
>{
T current;
Iterable<T>* obj;
public:
explicit iterator(T t,Iterable<T>* o) : obj(o) {current=t;}
iterator& operator++() {obj->next(current); return *this;}
iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
bool operator==(iterator other) const {return current == other.current;}
bool operator!=(iterator other) const {return !(*this == other);}
const T& operator*() const {return current;}
};
iterator begin() {return iterator(start,this);}
iterator end() {return iterator(stop,this);}
};
When i tried to use this iterator, I got different results when invoked differently:
for(auto S=SI.begin();S!=SI.end();S++)
{
cout << *S << "\n";
//cout << contains(seqs,S) << "\n";
if(!contains(seqs,*S))
seqs.push_back(*(new Sequence(*S)));
}
gave different results from:
for(Sequence S : SI)
{
cout << S << "\n";
//cout << contains(seqs,S) << "\n";
if(!contains(seqs,S))
seqs.push_back(*(new Sequence(S)));
}
even in the loop.
My SeqIter class (SI is object of this class) is as follows:
class SeqIter : public flex::Iterable<Sequence>
{
int n;
public:
SeqIter(int s) : Iterable(Sequence(copyList(0,s),s),Sequence(copyList(3,s),s)) {n=s;}
void next(Sequence& s)
{
char ch;
for(int i=0;i<n;i++)
{
ch=nextBase(s[i]);
s[i]=ch;
if(ch!=0)
break;
}
}
};
Sorry if this is too much code, but I do not know how much code is required.
Also, a brief explanation on the Sequence class:
It is a class that has an array of numbers (in this case I tried with 3), and it generates next sequences based on the first, i.e. 000, 100, 200, 300; 010,110 ...
Each digit ranges from 0-3 (both included)
I am unable to understand why both loops give different sequences (first gives 000 100 200 300 010 110 whereas second gives 000 100 200 300 000 110)
I thought both the loops were fundamentally same, and that the first was just the expansion of the second. Is that not so?
Also sequence class: (Sorry for delay, but I guess this is the problem)
class Sequence
{
int size=1;
char* bps;
public:
Sequence() {size=0;}
Sequence(int s)
{
size=s;
bps=new char[s];
}
Sequence(char* arr,int s)
{
size=s;
bps=arr;
}
Sequence(const Sequence& seq)
{
size=seq.size;
bps=new char[size];
strcpy(bps,seq.bps);
}
String toString() const {return *(new String(bps,size));}
inline char* toCharArray() {return bps;}
inline int getSize() const {return size;}
//operator overloading
public:
bool operator==(const Sequence& s2) const
{
if(s2.size!=size)
return false;
String r1=toString();
String r2=s2.toString();
return (r1==r2 || r1==r2.reverse());
}
inline bool operator!=(const Sequence& s2) const {return !operator==(s2);}
const char& operator[](int n) const
{
if(n>=size)
throw commons::IndexOutOfBoundsException(n,size);
return bps[n];
}
char& operator[](int n)
{
if(n>=size)
throw commons::IndexOutOfBoundsException(n,size);
return bps[n];
}
Sequence& operator=(const Sequence& seq)
{
size=seq.size;
bps=new char[size];
strcpy(bps,seq.bps);
}
};
Sorry everyone. Answering my own question after debugging:
In my Sequence class, I was using strcpy in copying char*, where the array did not end with a '\0'
Probably that caused the error:
I read online a bit more to find that the expansion was as follows:
for(Sequence S : seqs)
{
...
}
is equivalent to
for(auto i=SI.begin();i!=SI.end();i++)
{
Sequence S=*i;
...
}
So in the assignment, (S=*i) the data was not properly copied.
Sorry for all the trouble
fixed by removing assignment operator overload, and changing copy-constructor to:
Sequence(const Sequence& seq)
{
size=seq.size;
bps=new char[size];
for(int i=0;i<size;i++)
bps[i]=seq[i];
}

operator overloading opertator + cant convert from pointer to const

i have a sparse matrix that is created with two arrays and each array index have a linked list the non zero numbers are in there including the i and j indexs
the header
class MNode {
public:
double _data;
int _indexI, _indexJ; // the place of the node in the matrix
// clarification: _nextRow is a pointer to the next columns in the row
MNode* _nextRow, *_nextCol;
MNode(double data, int i, int j);
};
private:
string _type;
MNode** _rowHead, **_colHead;
int _rowSize, _colSize;
int _elemNum;
void setValue(int, int, double);
void removeElement(int, int);
void insertNode(MNode*);
bool IsExist(int, int);
void setElementByType(int i, int j, double data);
public:
// construct a 'rows X cols' matrix.
SMatrix(int rows, int cols,string type);
// set the (i,j) element to be 'data'
void setElement(int i, int j, double data);
// destroy this matrix.
~SMatrix();
double getElement(int, int);
friend std::ostream& operator<<(std::ostream& os, const SMatrix& mat);
SMatrix& operator = (const SMatrix& other);
SMatrix & operator+(const SMatrix & other) const;
};
the cpp here is the overloading + function i get an erorr
cannot convert this pointer to const SMatrix to Smatrix&
SMatrix &SMatrix::operator +(const SMatrix& other) const {
SMatrix temp(3, 3, "any") ;
if (other._rowSize == this->_rowSize&&other._colSize == this->_colSize&&other._type == this->_type) {
for (int j = 0; j < other._colSize; j++) {
for (int i = 0; i < other._rowSize; i++) {
temp.setElement(i, j, (other.getElement(i, j) + this->getElement(i, j)));
}
}
}
return temp;
}
here is the contructor
SMatrix::SMatrix(int rows, int cols,string matType )
{
_type = matType;
_rowSize = rows;
_colSize = cols;
_elemNum = 0;
_rowHead = new MNode*[rows];
if (!_rowHead)
{
cout << "allocation error";
exit(1);
}
_colHead = new MNode*[cols];
if (!_colHead)
{
cout << "allocation error";
exit(1);
}
for (int i = 0; i < rows; i++)
{
_rowHead[i] = NULL;
}
for (int i = 0; i < cols; i++)
{
_colHead[i] = NULL;
}
}
iam not sure what i need to do the signature of the function is given and cant be chanbged any idea?
You've declared other to be a reference to const:
SMatrix & operator+(const SMatrix & other) const;
^^^^^
You call the member function getElement on that reference:
temp.setElement(i, j, (other.getElement(i, j) + this->getElement(i, j)));
^^^^^^^^^^^^^^^^
You've declared getElement to be non-const:
double getElement(int, int);
^
You may only call const member functions on const references.
the signature of the function is given and cant be chanbged any idea?
If the signature of getElement can't be changed, then you've been dealt a badly written signature. There should be no good reason why a getter couldn't be const. That said, since you're within the class, you can access all members directly without using a getter.
There's another bug. You've declared operator+ to return a reference.
SMatrix &SMatrix::operator +(const SMatrix& other) const
^
But you return a local automatic variable temp:
SMatrix temp(3, 3, "any") ;
// ...
return temp;
Automatic variables are destroyed at the end of the function. Therefore the returned reference will always be dangling and any use of it would have undefined behaviour.
the signature of the function is given and cant be chanbged any idea?
If the signature of operator+ can't be changed, then you've been dealt a badly written signature. The function really should return by value. There's no sensible solution that could return a reference. Using a static local would technically work, but that has some limitations on usage that aren't apparent from the interface.

How to fix this C3848 error on vs2013?

I'm trying to implement Best First Search using C++ on VS2013. Below is the code.
//node for tree
struct Node
{
Node(std::string const& s, std::string const& p)
: state(s), path(p)
{}
const std::string state;
const std::string path;
};
//heuristic functor
struct ManhattanDistance
{
std::size_t operator()(std::string const& state, std::string const& goal)
{
std::size_t ret = 0;
for (int index = 0; index != goal.size(); ++index)
{
if ('0' == state[index])
continue;
auto digit = state[index] - '0';
ret += abs(index / 3 - digit / 3) + abs(index % 3 - digit % 3);// distance(row) plus distance(col)
}
return ret;
}
};
//functor to compare nodes using the heuristic function.
template<typename HeuristicFunc>
struct GreaterThan
{
explicit GreaterThan(HeuristicFunc h, std::string const& g = "012345678")
: goal(g), heuristic(h)
{}
bool operator()(Node const& lhs, Node const& rhs) const
{
return heuristic(lhs.state, goal) > heuristic(rhs.state, goal);
return true;
}
const std::string goal;
const HeuristicFunc heuristic;
};
When testing this code in Unit Test, compiler complained that :
Error 1 error C3848: expression having type 'const ai::search::ManhattanDistance' would lose some const-volatile qualifiers in order to call 'size_t ManhattanDistance::operator ()(const std::string &,const std::string &)'
How to understand this error? How to fix it?
Your method std::size_t ManhattanDistance::operator()(std::string const& state, std::string const& goal) is not declared const, yet you try to call it on a const ManhattanDistance object. The compiler is correctly rejecting this ill-formed program.
Change the defining line to declare the method const:
std::size_t operator()(std::string const& state, std::string const& goal) const
// ^^^^^

C++ - get const access to sub string of a string

Say I have a Storage class:
class Storage
{
public:
const string& get() const { return m_data; }
const char& get(int ind) const { return m_data[ind]; }
const string& get(int s_ind, int e_ind) const { /* TBD */ }
private:
string m_data; ///< Data is so big that part of it is stored on disk
}
Say I have a Writer class that gets const Storage& and needs to access its data.
My question, is there a way to implement:
const string& get(int s_ind, int e_ind) const;
i.e, get const access to only a part of a string.
Notes:
get() is called countless of times and it is the bottleneck of my application. I'd like to avoid allocating new objects when accessing data.
is there a way to implement:
const string& get(int s_ind, int e_ind) const;
i.e, get const access to only a part of a string.
Definitely not.
What is often done - and may resolve your bottleneck - is to create a class that stores a const char* and size_t (or equally begin and end const char*s, or iterators but there's no reason to limit this to use for data in std::strings).
You could then create an object that "references" text inside a string, and use it until any of the events that would invalidate an iterator or reference to those characters happens - see the Standard or e.g. cppreference. It's possible to support stream output, comparisons, indexing etc. driven off the std::string hosted data.
Clearly you won't be able to pass such a class to functions that hardcode std::string type, but you could write it to have a similar interface, which should lessen pain.
Just as a taster (hasn't seen a compiler / flesh out as needed)...
class Text_Ref
{
public:
Text_Ref(const char* p, size_t n) : p_(p), n_(n) { }
// intuitive values for &text_ref[x] BUT text_ref[n] may not be nul
const char& operator[](size_t o) const { return p_[n]; }
*** OR ***
// text_ref[n] is nul BUT can't use &text_ref[x]
char operator[](size_t o) const { return o == n ? '\0' : p_[n]; }
// same design trade off as the operator[] alternatives above
char at(size_t o) const
{
if (o > n) throw std::out_of_range();
return o == n ? '\0' : p_[n];
}
bool empty() const { return n == 0; }
size_t size() const { return n; }
size_t length() const { return n; }
int compare(const char* p) const
{
do
{
if (*p != *p_)
return (int)*p_ - *p;
} while (*p);
return 0;
}
bool operator< (const char* p) const { return compare(p) < 0; }
bool operator<=(const char* p) const { return compare(p) <= 0; }
bool operator==(const char* p) const { return compare(p) == 0; }
bool operator!=(const char* p) const { return compare(p) != 0; }
bool operator>=(const char* p) const { return compare(p) >= 0; }
bool operator> (const char* p) const { return compare(p) > 0; }
private:
const char* p_;
size_t n;
};
inline std::ostream& operator<<(std::ostream& os, const Text_Ref& t)
{
return os.write(t.data(), t.size());
}

What are the serious uses of returning the this pointer from a function?

Following is a fancy code:
class B
{
private:
int sum;
public:
B ()
{
sum = 0;
}
B& add (int number)
{
sum =+ number;
return *this;
}
};
int main ()
{
B obj;
obj.add (1).add (2).add (3). add (4);
}
Fine, what are the "serious" uses of returning the this pointer from a function call?
An example would be;
class basic_ostream
: ...
{
basic_ostream& operator<<(bool n);
You really want to return this to be able to chain to;
std::cout << boolValue << std::endl;
mycode $ fgrep -r 'return *this' /usr/include/c++/4.4.3 | wc -l
592
mycode $
One use of this is for the Named Parameter Idiom. It depends on method chaining.
class Person;
class PersonOptions
{
friend class Person;
string name_;
int age_;
char gender_;
public:
PersonOptions()
: age_(0), gender_('U')
{}
PersonOptions& name(const string& n) { name_ = n; return *this; }
PersonOptions& age(int a) { age_ = a; return *this; }
PersonOptions& gender(char g) { gender_ = g; return *this; }
};
class Person
{
string name_;
int age_;
char gender_;
public:
Person(const PersonOptions& opts)
: name_(opts.name_), age_(opts.age_), gender_(opts.gender_)
{}
};
Person p = PersonOptions().name("George").age(57).gender('M');
Person p = PersonOptions().age(25).name("Anna");
The initial reason wass for chaining mathematical operations, like this:
class mynumberclass {
int internal;
public:
mynumberclass(int);
mynumberclass operator+(const mynumberclass&) const;
mynumberclass operator-(const mynumberclass&) const;
mynumberclass operator*(const mynumberclass&) const;
mynumberclass operator/(const mynumberclass&) const;
mynumberclass operator%(const mynumberclass&) const;
mynumberclass& operator+=(const mynumberclass&);
mynumberclass& operator-=(const mynumberclass&);
mynumberclass& operator*=(const mynumberclass&);
mynumberclass& operator/=(const mynumberclass&);
mynumberclass& operator%=(const mynumberclass&);
};
int main() {
mynumberclass a(3);
mynumberclass b(4);
mynumberclass c = (a * b + b) / 2; //this chains 3 of the above operators
}
without chaining, that code would have to look like this:
int main() {
mynumberclass a(3);
mynumberclass b(4);
mynumberclass c(a);
c *= b;
c += b;
c /= 2;
}
FredLarson also mentions the Named Parameter Idiom, which is certainly an awesome thing you can use chaining for.
The first thing that comes to mind is chaining functions to perform operations on the same object. jQuery, although not C++, has shown that this can be a very useful paradigm.