I am trying to implement a comparator function, and coming from a JavaScript background attempted to chain them like so:
int MyClass::compare(MyClass & other) {
return MyClass.x.compare(other.x) || MyClass.y.compare(other.y);
}
That is, compare the objects' x values, and if they are equal compare the objects' y values.
I immediately realized this wouldn't work, because the OR function in c++ returns a bool rather than the last evaluated value.
Other than literally writing an if statement, like
int result = MyClass.x.compare(other.x);
if (result) {
return result;
}
result = MyClass.y.compare(other.y);
return result;
, is there is a concise way to write this expression?
Related
When doing something like this:
i2 = i++;
The ++ operator will return i, and then it will increment i by one.
Can a function also return something and then execute its code?
No, once the scope of a function is over (at the closing }), no further code can be executed.
However, the function can store the old state of the input, modify the input, and return the old value of the input. This gives the effect of executing code after the function returns a value. As an example:
int f(int &n) {
int x = n; // store input
n = 42; // input is modified before return
return x; // old input is returned
}
int b = f(a); // b is equal to a
// but now a is 42
As you have observed, post-increment is an example of where such behavior is useful. Another example would be std::exchange, which gives the appearance of modifying the input after returning a value.
If you were to implement postfix increment by yourself, you would first store the original value, then use increment but still return the original value:
Number Number::operator++ (int)
{
Number ans = *this;
++(*this);
return ans;
}
You may check this FAQ for more details: https://isocpp.org/wiki/faq/operator-overloading#increment-pre-post-overloading
So there is no function code execution after return in C++.
i have a recursive search function that returns the index of my vector where the search key was found
However sometimes my vector can have two different positions that have the same key but my function only returns the first one.
here is my function:
int IdeaBank::twoSearchAND(int first, int last, string word_1, string word_2)
{
if (last == first)
return -1;
if (newIdea[first].foundWordInBoth(word_1)
&& newIdea[first].foundWordInBoth(word_2))
return first;
else
return twoSearchAND(first+1,last,word_1,word_2);
}
and here is how i am using it in my main
int first = 0;
int last = ideaBank.newIdea.size();
int index_found;
index_found = ideaBank.twoSearchAND(first, last, search_word1, search_word2);
ideaBank.displayIdeaByID(index_found);
my idea was to loop through n amount of times were n is the number of index's it returns but i wasnt too sure how to achieve that
is there a way for me to get all the returned values from my function?
Edit: this is for a school project and must use recursion
A function can return at most one value. However, a class can have multiple sub objects. Therefore you can return multiple sub objects within one return by returning a class. To return exactly two values, you can use std::pair for example.
Note that this algorithm is already in the standard libarary: std::search_n, so there is no need to re-write it. Also, it is an inherently iterative algorithm and there is no need to complicate it by using recursion.
You might collect results into a container such as std::vector.
To avoid extra copies to concatenate vectors if used as return value, I use it as output parameter in the recursive method.
void IdeaBank::twoSearchAND(int first, int last,
const std::string& word_1, const std::string& word_2,
std::vector<int>& res)
{
if (last == first)
return;
if (newIdea[first].foundWordInBoth(word_1)
&& newIdea[first].foundWordInBoth(word_2))
res.push_back(first);
twoSearchAND(first + 1, last, word_1, word_2, res);
}
std::vector<int> IdeaBank::twoSearchAND(const std::string& word_1,
const std::string& word_2)
{
std::vector<int> res;
int first = 0;
int last = newIdea.size();
twoSearchAND(first, last, word_1, word_2, res);
return res;
}
And usage is similar to:
auto indexes_found = ideaBank.twoSearchAND(search_word1, search_word2);
for (auto index_found : indexes_found) {
ideaBank.displayIdeaByID(index_found);
}
I'm implementing an algorithm that implies a lot of checking whether elements are in a set/list. I was using std::vector containers but time was increasing exponentially as the vector would grow.
I've decided I would try using std::set containers in order not to have to explore the entire container to know whether it contains a certain element.
I implemented the following function that checks whether an element is part of a given set:
bool in_set(set<Node> node_set){
return node_set.find(*this) != node_set.end();
}
However, that function is taking around 2s for very small sets (1-3 elements) which makes my entire algorithm unusable.
The custom class I'm using look like this:
class Node{
public:
int d;
int h_score;
int coordinates [3];
Node* parent_address;
};
The comparison operator that I implemented look like this:
bool operator<(Node other) const{
return concatenate(concatenate(this->coordinates[0], this->coordinates[1]), this->coordinates[2]) <
concatenate(concatenate(other.coordinates[0], other.coordinates[1]), other.coordinates[2]);
}
Edit: The concatenate function does not seem to take a lot of time while executing, it looks like this:
int concatenate(int i, int j) {
int result = 0;
for (int x = i; x <= j; x++) {
result = result * 10 + x;
}
return result;
}
Do you know why it is taking so much time, and more importantly, how to make it faster?
First of all, you can try to pass Set as const & and not in operator< also as const &.
bool in_set(const set<Node>& node_set){
return node_set.find(*this) != node_set.end();
}
And
bool operator<(const Node& other) const
It will use ref instead of a copy of your set and Node objects.
Do you know why it is taking so much time
concatenate(1, 100000000) takes 1.3 second on my raspberry pi, that way to do is too slow, and in fact useless
Note also that because of the possible overflows concatenate can give the same result for different nodes, this is non compatible for an operator<
how to make it faster?
you have to find something else than these calls of concatenate to implement your operator<
What is your need ? is the order in the set is important or it can be replaced by any one else ?
It is not mandatory to create a unique identifier to compare two nodes, compare them directly, for instance :
bool operator<(const Node & other) const{
if (coordinates[0] < other.coordinates[0])
return true;
if (coordinates[0] >= other.coordinates[0])
return false;
if (coordinates[1] < other.coordinates[1])
return true;
if (coordinates[1] >= other.coordinates[1])
return false;
return (coordinates[2] < other.coordinates[2]);
}
To understand that operator< works you can consider node.coordinates supports a big number having 3 times the size of an int, so I compare the higher bits, then if equals the medium bits, then if equals the lower bitsused for a set
Your operator< takes a copy of the Node. There's also no need to create strings to compare, the built-in tuple class can do that:
How about:
bool operator<(const Node& other) const {
return std::make_tuple(coordinates[0], coordinates[1], coordinates[2]) <
std::make_tuple(other.coordinates[0], other.coordinates[1], other.coordinates[2]);
}
** Please don't criticize the purpose of the code itself. It's from Pat Morin's Open Data Structures book. Not my first choice, its assigned reading/practice. I just wanted to know if there is a way to differentiate, or a better way to go about this. Textbook--> http://opendatastructures.org/ods-cpp/**
** Another note: I'm coming from Java, where this would be allowed. My code still compiles, it just "fixes" it**
I'm surprised nothing like this has come up before because it seems like such a simple question. Perhaps it's buried or I'm not using the correct terminology.
I have a for loop that goes through the data in a vector. I need to return the value being searched for if it's found. What if it's not found? Here is my code.
int find(int x) {
for(int i=0;i<bag.size();i++){
// if x is equal to data, return data
if (bag[i]==x){
return bag[i]; // ends loop as soon as one instance is found
}
}
// if we made it this far, no match was found.
return NULL;
}
Pretty simple. Let's say 0 is one of the valid values that I might need to record and search for. As it is, it actually returns 0, not "NULL". Research says it is one and the same. How can I specify or differentiate? Other than returning an obsqure number that won't come up in the program because we may not always have that luxury (like -1 or -9999999). For example, searching for your account balance. No number is impossible.
Why would you return the value you are searching for from a find function? You already know the value, its the one you passed to the function. Return the position of the found element instead, as this information is much more useful. When the value isn't found, you can return a special position, like -1. Or you can follow the model of the standard library and return the end iterator, which signifies a position that is one past the end of the range.
You can write the function in several ways
bool find( int x )
{
std::vector<int>::size_type i = 0;
while ( i < bag.size() && bag[i] != x ) i++;
return i != bag.size();
}
Or
std::vector<int>::size_type find( int x )
{
std::vector<int>::size_type i = 0;
while ( i < bag.size() && bag[i] != x ) i++;
return i;
}
Or
#include <algorithm>
//...
std::vector<int>::iterator find( int x )
{
return std::find( beg.begin(), bag.end(), x );
}
And use the functions correspondingly the following ways
if ( find( x ) ) { /*...*/ }
if ( find( x ) != bag.size() ) { /*...*/ }
if ( find( x ) != bag.end() ) { /*...*/ }
As for your general question in the title of the post
What if I need to differentiate 0 from NULL in C++?
then you need fo use nullptr instead of NULL that to differentiate 0 from NULL.:)
#define XOR_MSB(x) (x^0x80000000)
int find(bool found) {
return found ? XOR_MSB(0) : NULL;
}
int main()
{
int value = find(false);
if (value == NULL) printf("not found\n");
else printf("%d\n", XOR_MSB(value));
value = find(true);
if (value == NULL) printf("not found\n");
else printf("%d\n", XOR_MSB(value));
return 0;
}
you're talking about an evil practice, coming from Java and C# developers where you can return null as invalid result.
well, you can't do it in C++.
Java and C# declares almost everything on the heap, and accessing objects is done done always by the reference. this means you always return a pointer from a function, and you can always return a null as a return value.
this is not so possible in C++ when a function does not return a pointer. for example , the function std::string returnString() can't return null as a return value.
more over, you should not return null as invalid output. this is wrong on so many levels even in C# and Java! if your function fails, simply throw an exception, or make your return value be passed as reference-argument and make the function return true or false.
you can also find less-agressive solutions like returning -1 (like indexOf() in javascript) or return somthing like std::string::npos or std::vector:end which are more C++ STL tuned.
This is what boost::optional<T> is for. Effectively, this type represents "There may be a T, but there may not be a T". The user may check if there is a T or not. Ideally you would not depend on any special value of T but use an optional<T> instead. optional<T> is fully generic and may apply to pretty much any T you may need to use, it does not depend on some special value or state of T.
boost::optional<int> find(int x) {
for(int i=0;i<bag.size();i++){
// if x is equal to data, return data
if (bag[i]==x){
return bag[i]; // ends loop as soon as one instance is found
}
}
// if we made it this far, no match was found.
return boost::none;
}
int main() {
if (auto opt = find(5))
std::cout << *opt;
}
Do not ever use NULL, it is a terrible thing. Always use nullptr which is substantially safer and one of the reasons why it is safer is because your wrong code would not compile.
For lambda expressions, I don't quite get the usefulness of closures in C++11.
auto f = [] (int n, int m) { return n + m };
std::cout << f(2,2);
versus.
int n = 2;
auto f = [n] (int m) { return n + m };
std::cout << f(2);
This is a very basic and primitive example. I'm guessing that closures play an important part in other kinds of statements, but my C++ book doesn't clarify this (so far).
Why not include the closure as a parameter?
OK, a simple example, remove all the x's from a string
char x = 'x';
std::string s = "Text to remove all 'x's from";
s.erase(std::remove_if(s.begin(), s.end(), [x](char c) {return x == c;}), s.end());
Borrowed and modifed from http://en.cppreference.com/w/cpp/algorithm/remove
In this example, remove_if() only takes a single parameter, but I need two values for the comparison.
Closures are not always called immediately. They are objects which can be stored and called later when the data necessary to successfully execute the lambda function may no longer be in scope or easily accessible from the call site.
It's possible to to store any necessary data along with the closure but it's so much simpler for the closure to grab anything it needs when it's created and use it when it's eventually called. It provides a form of encapsulation.
This also decreases code coupling because if you were to store the data along with the code then the caller could only work with the specific objects you decided to store. Since a closure carries its own data along with it, it can work with any data it needs.
Here's an greatly oversimplified real-life example. I built a database server which needed to support fields with multiple values. The problem was that when results were displayed, it was important to highlight which values actually caused a record to match the search criteria. So, the query parser would spit out a predicate in the form of a closure which would indicate whether or not it was a matching value.
It looked something like this:
std::function< bool(int value) > parser::match_int(int search_val) {
return [=](int value) { value == search_val; };
}
That closure got stored in a collection. When it was time to render the record, I could easily determine which values needed to be highlighted. Keep in mind that the parser and any associated data is now gone:
void render_values(std::function< bool(int value) > pred, std::vector<int> values) {
for (int value : values) {
if (pred(value))
render_highlight(value);
else
render_normal(value);
}
}