Usage of comparator in C++ - c++

Following is the c++ code to Merge k Sorted Lists. But i was confused reading the first 4 lines of code. I know what it does just confused how it does it. Could anybody explain these lines to me?
Why use struct?
What are the "()" for after "operator"?
Why use ">" rather than "<" since all the lists including the result list are in ascending order?
struct compare {
bool operator() (ListNode* &left, ListNode* &right) {
return left->val > right->val;
}
};
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
priority_queue<ListNode *, vector<ListNode *>, compare> heap;
for (int i = 0; i < lists.size(); i++) {
if (lists[i]) heap.push(lists[i]);
}
ListNode *dummy = new ListNode(0);
ListNode *cur = dummy;
while (!heap.empty()) {
ListNode *min = heap.top();
heap.pop();
cur->next = min;
cur = min;
if (min->next) {
heap.push(min->next);
}
}
return dummy->next;
}
};

Your struct compare is what is known as a functor or a function object.
struct compare
{
bool
operator() (const ListNode& left, const ListNode& right) const
{
return left.val > right.val;
}
};
void
example_usage(const ListNode& left, const ListNode& right, const compare cmp)
{
if (cmp(left, right))
std::cout << "left is greater" << std::endl;
else
std::cout << "right is greater" << std::endl;
}
(I have changed the signature since using references to pointers and making these non-const disturbed me too much.)
It is a convenient alternative to using function pointers in many situations. Most important, when used in templates (as in your example) the compiler is usually able to inline calls to operator (). Using function pointers this is not so easy.
It is not clear whether this is relevant in your example but generally, a functor has the advantage that it can be declared anywhere (also inside function bodies) while functions may only be declared at global scope or as class members. This allows better encapsulation using functors. Since C++11, we have lambdas as yet another alternative:
auto cmp = [](const ListNode& left, const ListNode& right)->bool{
return left.val > right.val;
};
It can be used just like the functor. (Under the hood, the compiler will most likely create a functor if you give it a lambda expression.)

Why use struct?
There is no need to use a struct here, although it doesn't hurt.
What are the "()" for after "operator"?
Look for operator overloading tutorial.
Why use ">" rather than "<" since all the lists including the result list are in ascending order?
It's convention to use < for comparisions such as these, so I don't know why, except to be awkward.
Furthermore the parameters should be (const ListNode* left, const ListNode* right) and if inside a struct, the member function should be made const as well. There is no need to take them by reference here. I would also consider whether you need a data structure of pointers and dynamic allocation here.

Why use struct?
It can be a struct or a class. They are essentially the same thing other than 1. members of structs are default public and members of classes are default private, and 2. general opinions on how people should use structs for POD (plain old data) and classes for everything else.
What are the "()" for after "operator"?
This one's fun. ... operator()(...) defines an overload for the function call operator. Whenever you call a function, you will definitely use this operator, encapsulating the arguments within the brackets and having the return value be the result of the expression.
On a side note, a class or struct with an overloaded function call operator is normally referred to as a functor.
Why use ">" rather than "<" since all the lists including the result list are in ascending order?
This is also another interesting question. The idea is that the STL (Standard Template Library) is meant to be used by almost everyone that uses C++, and is meant to provide convenience in performing certain operations. As such, all the tools in the STL are built to work for any types, including user-defined types.
However, user-defined types do not have operators such as < and > overloaded by default, so users will have to overload them.
The result of a > b is essentially the same as b < a. Now imagine if some of these tools use <, while others use >. Everyone would have to overload both operators even though they are just complements of each other and can be used to substitute each other.
Therefore, a standard was set such that the STL will only use the > operator and only require you to overload that one operator.
On a side note, instead of writing your own comparison functor, you can use the std::less templated functor for simple operations like a less-than comparison, and the std::function for more complex operations.
Thank you for reading.

Related

How to understand this expression in C++ struct?

struct Task{
int value,time,deadline;
bool operator < (const Task& t1)const{
return d<t1.deadline;
}
}task[1000];
I've read this block of code of struct initialization.
the first line, initialize variables, is easy to grasp.
What about the second line? the bool operator thing. Seems like some kind of sorting rules. I have never seen any code like this in cpp before, could someone help me to understand it?
What you observe is called operator overloading. In this case the operator< is overloaded for class Task.
This is done in order to be able to write something like this.
Task t1{1,2,3};
Task t2{2,3,4};
if(t1 < t2) //note, the operator< is called
{
//do your thing
}
To add to the answer, I would like to point out that the variables are not initialized (in traditional sense). It is so called default initialization or, rather, a lack of initialization as the variables will be of whatever value that happened to be in the memory at that time.
To zero-initialize the array, you'll need to use the following syntax (that resembles calling a default constructor of an array)
struct Task{
int value, time, deadline;
bool operator < (const Task& t1) const {
return deadline < t1.deadline;
}
} task[1000]{};
...Well, it's simple in your case, since you don't have any user-declared constructors, but in other cases it may become tricky. Read this if you're interested value-initialization.
(And {} is a new syntax for constructing objects introduced in C++11. The prior syntax () has several issues: it does not check that arguments are narrowed, and it suffers from the most vexing parse problem, when Foo aVariable(std::string("bar")); is parsed as function declaration (see).)

How to define []= and at() = for a custom collection?

EDIT: This question is not for overriding the operator [] I know how to do that
I have implemented My own collection class, and for assigning data I would like to provide the same operators/functions as std::vector.
However, I have not been able to find a way to define the operators [index]=elm and at(index) = elm.
I am not even completely sure what to terms to search for as these two are not exactly operators
Define your operator[] overload and your at function to return a reference to the specified item. You can then assign the new value through that reference.
There is no []= operator. If your operator[] function returns a reference that can be assigned to, that's all you need.
Simple example to demonstrate the idea.
struct Foo
{
int i;
int& operator[](int) { return i; };
int operator[](int) const { return i; };
}
Now you can use
Foo f;
f[10] = 20; // The index is not used by Foo::operator[]
// This is just to demonstrate the syntax.
You need to do the same with the at() function.

Emulate copy-assignment operator for lambdas in C++

This question has two parts
Firstly, can someone explain the rationale behind C++ disabling the copy-assignment operator for lambdas? If you're going to allow the copy constructor, why not the copy-assignment operator?
Secondly, how do you best overcome this limitation without forcing people to write C++03 style functors, or using std::function (the functions I'm dealing with are tiny, and I'd like the compiler to inline them wherever possible)?
Background:
I'm trying to implement a flat_map like operation in a stream processing library I'm writing, similar to flatMap in Scala or other functional languages. As a result, I need to create an iterator that iterates over a list of iterators. Each time the flat_map iterator is de-referenced a lambda associated with the inner iterator is executed. The outer iterator needs to switch the inner iterator each time the inner iterator reaches the end. Since the inner iterator contains a lambda, and therefore does not have a copy-assignment operator, it's not possible to switch it. Technically I could solve the problem using dynamic allocation, so that I always call the copy-constructor, but that doesn't seem like the right approach. Here is a snippet of code that might help highlight the problem:
template <typename Iter>
class flat_map_iterator {
public:
flat_map_iterator& operator++() {
++it_inner_;
if (it_inner_ == (*it_outer_).end()) {
++it_outer_;
// ERROR: cannot be assigned because its copy assignment operator is implicitly deleted
it_inner_ = (*it_outer_).begin();
}
return *this;
}
private:
Iter it_outer_;
typename Iter::value_type::iterator it_inner_;
};
Edit:
Thanks for the really quick responses. Here is a use case example:
int res = ftl::range(1, 4).map([](int a){
return ftl::range(a, 4).map([a](int b){
return std::make_tuple(a, b);
});
})
.flat_map([](std::tuple<int, int> x){ return std::get<0>(x) * std::get<1>(x); })
.sum();
assert(res, 25);
The ftl::range(begin, end) function returns a lazy iterator over the range [begin, end).
It's not that C++ disables the copy-assignment operator for lambda per-se, but that by default members in a lambda object are saved as const, and then the assignment operator can basically do nothing to assign to them, and so it is not generated. If you want lambdas to not hold members as const, you use the [...](...) mutable {...} syntax.
The other thing is that I'm not entirely sure what you get out of assigning lambdas. I mean, if you're going to re-use the lambda type (and functionality) and simply bind it to different variables, you're already working against the nice lambda capture syntax, and might as well have it be a normal function object. Assigning one type of lambda to another one is impossible. This means that you can not provide different lambda implementations when you hold the lambda itself by value.
If this is still what you're going for, I think dynamic allocation (e.g. using unique_ptr) is fair game.
And if you really want to avoid it, you could manually destruct and re-construct your lambda, as the following example illustrates:
#include <iostream>
template <class T>
struct LambdaContainer {
LambdaContainer(const T& lambda)
: lambda{lambda} {}
void resetLambda(const T& lambda) {
this->lambda.~T();
new (&this->lambda) T{lambda};
}
T lambda;
};
int main()
{
int i = 1;
auto l = [=]() {
std::cout << i;
};
using LT = decltype(l);
LambdaContainer<LT> lc{l};
lc.resetLambda(l);
}

Assignment of an operation without intermediate object

Given a class like this:
class Vec{
int comp[2];
public:
void add(Vec& vec, Vec& vec2){
comp[0] = vec.comp[0] + vec2.comp[0];
comp[1] = vec.comp[1] + vec2.comp[1];
}
Vec operator+ (Vec& vec){
Vec res;
res.comp[0] = comp[0] + vec.comp[0];
res.comp[1] = comp[1] + vec.comp[1];
return res;
}
};
There are two member functions that essentially do the same thing, which is add two Vecs together. The difference, of course, is that there are no intermediate values involved in the add function, whereas operator+ declares a local object of Vec.
My question is, is there any way to define operator+ in combination with operator= to have the same semantics as add, having no intermediate values? The rationale is to decrease the amount of intermediate values involved, for efficiency, yet keep the elegance of the operator syntax.
The C++ interface for the GMP library apparently is able to do this: http://gmplib.org/manual/C_002b_002b-Interface-General.html#C_002b_002b-Interface-General
An important feature of the implementation is that an expression like a=b+c results in a single call to the corresponding mpz_add, without using a temporary for the b+c part.
I'm wondering if there is some possible way to do this, or would GMP have to use some sort of workaround for this?
This is a bad idea, because it violates the natural assumptions most people have about the behavior of operators.
Unfortunately it is also very important (especially for libraries like gmpxx, which want to offer natural code using operators, high performance, and have huge objects as arguments). How do they achieve this? By using expression templates they can optimize expression at compile time. The idea is that operators don't return values directly but concrete instances of expression classes which then can be manipulated with meta-programming.
Expression templates are an rather advanced topic and you should be relatively certain that it will give a significant benefit to your code. In your example the size of the vectors simply isn't relevant enough.
Wiki Expression Templates
I see no real advantage for this as your objects are very small. But for things like dynamically allocated large vectors this could be useful.
One way to implement it is to create a temporary noop class to hold the unevaluated expression. This class would be convertible to Vec so that it becomes transparent to the user. The point is that you can now create an specialized operator= for the add expression. Some code (fill the gaps):
struct VecAdd;
struct Vec
{
Vec& operator=(const VecAdd& vecadd) { /*...*/ }
};
struct VecAdd
{
const Vec& v1;
const Vec& v2;
operator Vec() { return Vec(/*...*/); } // for things like: f(v+u);
};
VecAdd operator+(const Vec& a, const Vec& b) { return VecAdd{a, b}; }
This is what GMP actually does. But with a lot of macros and templates to make the code less repetitive.
How about operator+= which you then would use as myVec += otherVec

C++: STL troubles with const class members

It is an open ended question.
Effective C++. Item 3. Use const whenever possible. Really?
I would like to make anything which doesn't change during the objects lifetime const. But const comes with it own troubles. If a class has any const member, the compiler generated assignment operator is disabled. Without an assignment operator a class won't work with STL. If you want to provide your own assignment operator, const_cast is required. That means more hustle and more room for error. How often you use const class members?
EDIT: As a rule, I strive for const correctness because I do a lot of multithreading. I rarely need to implemented copy control for my classes and never code delete (unless it is absolutely necessary). I feel that the current state of affairs with const contradicts my coding style. Const forces me to implement assignment operator even though I don't need one. Even without const_cast assignment is a hassle. You need to make sure that all const members compare equal and then manually copy all non-const member.
Code. Hope it will clarify what I mean. The class you see below won't work with STL. You need to implement an assignment for it, even though you don't need one.
class Multiply {
public:
Multiply(double coef) : coef_(coef) {}
double operator()(double x) const {
return coef_*x;
}
private:
const double coef_;
};
You said yourself that you make const "anything which doesn't change during the objects lifetime". Yet you complain about the implicitly declared assignment operator getting disabled. But implicitly declared assignment operator does change the contents of the member in question! It is perfectly logical (according to your own logic) that it is getting disabled. Either that, or you shouldn't be declaring that member const.
Also, providing you own assignment operator does not require a const_cast. Why? Are you trying to assign to the member you declared const inside your assignment operator? If so, why did you declare it const then?
In other words, provide a more meaningful description of the problems you are running into. The one you provided so far is self-contradictory in the most obvious manner.
As AndreyT pointed out, under these circumstances assignment (mostly) doesn't make a lot of sense. The problem is that vector (for one example) is kind of an exception to that rule.
Logically, you copy an object into the vector, and sometime later you get back another copy of the original object. From a purely logical viewpoint, there's no assignment involved. The problem is that vector requires that the object be assignable anyway (actually, all C++ containers do). It's basically making an implementation detail (that somewhere in its code, it might assign the objects instead of copying them) part of the interface.
There is no simple cure for this. Even defining your own assignment operator and using const_cast doesn't really fix the problem. It's perfectly safe to use const_cast when you get a const pointer or reference to an object that you know isn't actually defined to be const. In this case, however, the variable itself is defined to be const -- attempting to cast away the constness and assign to it gives undefined behavior. In reality, it'll almost always work anyway (as long as it's not static const with an initializer that's known at compile time), but there's no guarantee of it.
C++ 11 and newer add a few new twists to this situation. In particular, objects no longer need to be assignable to be stored in a vector (or other collections). It's sufficient that they be movable. That doesn't help in this particular case (it's no easier to move a const object than it is to assign it) but does make life substantially easier in some other cases (i.e., there are certainly types that are movable but not assignable/copyable).
In this case, you could use a move rather than a copy by adding a level of indirection. If your create an "outer" and an "inner" object, with the const member in the inner object, and the outer object just containing a pointer to the inner:
struct outer {
struct inner {
const double coeff;
};
inner *i;
};
...then when we create an instance of outer, we define an inner object to hold the const data. When we need to do an assignment, we do a typical move assignment: copy the pointer from the old object to the new one, and (probably) set the pointer in the old object to a nullptr, so when it's destroyed, it won't try to destroy the inner object.
If you wanted to badly enough, you could use (sort of) the same technique in older versions of C++. You'd still use the outer/inner classes, but each assignment would allocate a whole new inner object, or you'd use something like a shared_ptr to let the outer instances share access to a single inner object, and clean it up when the last outer object is destroyed.
It doesn't make any real difference, but at least for the assignment used in managing a vector, you'd only have two references to an inner while the vector was resizing itself (resizing is why a vector requires assignable to start with).
I very rarely use them - the hassle is too great. Of course I always strive for const correctness when it comes to member functions, parameters or return types.
Errors at compile time are painful, but errors at runtime are deadly. Constructions using const might be a hassle to code, but it might help you find bugs before you implement them. I use consts whenever possible.
I try my best to follow the advice of using const whenever possible, however I agree that when it comes to class members, const is a big hassle.
I have found that I am very careful with const-correctness when it comes to parameters, but not as much with class members. Indeed, when I make class members const and it results in an error (due to using STL containers), the first thing I do is remove the const.
I'm wondering about your case... Everything below is but supposition because you did not provide the example code describing your problem, so...
The cause
I guess you have something like:
struct MyValue
{
int i ;
const int k ;
} ;
IIRC, the default assignment operator will do a member-by-member assignment, which is akin to :
MyValue & operator = (const MyValue & rhs)
{
this->i = rhs.i ;
this->k = rhs.k ; // THIS WON'T WORK BECAUSE K IS CONST
return *this ;
} ;
Thus, this won't get generated.
So, your problem is that without this assignment operator, the STL containers won't accept your object.
As far I as see it:
The compiler is right to not generate this operator =
You should provide your own, because only you know exactly what you want
You solution
I'm afraid to understand what do you mean by const_cast.
My own solution to your problem would be to write the following user defined operator :
MyValue & operator = (const MyValue & rhs)
{
this->i = rhs.i ;
// DON'T COPY K. K IS CONST, SO IT SHOULD NO BE MODIFIED.
return *this ;
} ;
This way, if you'll have:
MyValue a = { 1, 2 }, b = {10, 20} ;
a = b ; // a is now { 10, 2 }
As far as I see it, it is coherent. But I guess, reading the const_cast solution, that you want to have something more like:
MyValue a = { 1, 2 }, b = {10, 20} ;
a = b ; // a is now { 10, 20 } : K WAS COPIED
Which means the following code for operator =:
MyValue & operator = (const MyValue & rhs)
{
this->i = rhs.i ;
const_cast<int &>(this->k) = rhs.k ;
return *this ;
} ;
But, then, you wrote in your question:
I would like to make anything which doesn't change during the objects lifetime const
With what I supposed is your own const_cast solution, k changed during the object lifetime, which means that you contradict yourself because you need a member variable that doesn't change during the object lifetime unless you want it to change!
The solution
Accept the fact your member variable will change during the lifetime of its owner object, and remove the const.
you can store shared_ptr to your const objects in STL containers if you'd like to retain const members.
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <vector>
class Fruit : boost::noncopyable
{
public:
Fruit(
const std::string& name
) :
_name( name )
{
}
void eat() const { std::cout << "eating " << _name << std::endl; }
private:
const std::string _name;
};
int
main()
{
typedef boost::shared_ptr<const Fruit> FruitPtr;
typedef std::vector<FruitPtr> FruitVector;
FruitVector fruits;
fruits.push_back( boost::make_shared<Fruit>("apple") );
fruits.push_back( boost::make_shared<Fruit>("banana") );
fruits.push_back( boost::make_shared<Fruit>("orange") );
fruits.push_back( boost::make_shared<Fruit>("pear") );
BOOST_FOREACH( const FruitPtr& fruit, fruits ) {
fruit->eat();
}
return 0;
}
though, as others have pointed out it's somewhat of a hassle and often easier in my opinion to remove the const qualified members if you desire the compiler generated copy constructor.
I only use const on reference or pointer class members. I use it to indicate that the target of the reference or pointer should not be changed. Using it on other kinds of class members is a big hassle as you found out.
The best places to use const is in function parameters, pointers and references of all kinds, constant integers and temporary convenience values.
An example of a temporary convenience variable would be:
char buf[256];
char * const buf_end = buf + sizeof(buf);
fill_buf(buf, buf_end);
const size_t len = strlen(buf);
That buf_end pointer should never point anywhere else so making it const is a good idea. The same idea with len. If the string inside buf never changes in the rest of the function then its len should not change either. If I could, I would even change buf to const after calling fill_buf, but C/C++ does not let you do that.
The point is that the poster wants const protection within his implementation but still wants the object assignable. The language does not support such semantics conveniently as constness of the member resides at the same logical level and is tightly coupled with assignability.
However, the pImpl idiom with a reference counted implementation or smart pointer will do exactly what the poster wants as assignability is then moved out of the implementation and up a level to the higher level object. The implementation object is only constructed/destructed whence assignment is never needed at the lower level.
I think your statement
If a class has const any member, the
compiler generated assignment operator
is disabled.
Might be incorrect. I have classes that have const method
bool is_error(void) const;
....
virtual std::string info(void) const;
....
that are also used with STLs. So perhaps your observation is compiler dependent or only applicable to the member variables?
I would only use const member iff the class itself is non-copyable. I have many classes that I declare with boost::noncopyable
class Foo : public boost::noncopyable {
const int x;
const int y;
}
However if you want to be very sneaky and cause yourself lots of potential
problems you can effect a copy construct without an assignment but you have to
be a bit careful.
#include <new>
#include <iostream>
struct Foo {
Foo(int x):x(x){}
const int x;
friend std::ostream & operator << (std::ostream & os, Foo const & f ){
os << f.x;
return os;
}
};
int main(int, char * a[]){
Foo foo(1);
Foo bar(2);
std::cout << foo << std::endl;
std::cout << bar<< std::endl;
new(&bar)Foo(foo);
std::cout << foo << std::endl;
std::cout << bar << std::endl;
}
outputs
1
2
1
1
foo has been copied to bar using the placement new operator.
It isn't too hard. You shouldn't have any trouble making your own assignment operator. The const bits don't need to be assigned (as they're const).
Update
There is some misunderstanding about what const means. It means that it will not change, ever.
If an assignment is supposed to change it, then it isn't const.
If you just want to prevent others changing it, make it private and don't provide an update method.
End Update
class CTheta
{
public:
CTheta(int nVal)
: m_nVal(nVal), m_pi(3.142)
{
}
double GetPi() const { return m_pi; }
int GetVal() const { return m_nVal; }
CTheta &operator =(const CTheta &x)
{
if (this != &x)
{
m_nVal = x.GetVal();
}
return *this;
}
private:
int m_nVal;
const double m_pi;
};
bool operator < (const CTheta &lhs, const CTheta &rhs)
{
return lhs.GetVal() < rhs.GetVal();
}
int main()
{
std::vector<CTheta> v;
const size_t nMax(12);
for (size_t i=0; i<nMax; i++)
{
v.push_back(CTheta(::rand()));
}
std::sort(v.begin(), v.end());
std::vector<CTheta>::const_iterator itr;
for (itr=v.begin(); itr!=v.end(); ++itr)
{
std::cout << itr->GetVal() << " " << itr->GetPi() << std::endl;
}
return 0;
}
Philosophically speaking, it looks as safety-performance tradeoff. Const used for safety. As I understand, containers use assignment to reuse memory, i.e. for sake of performance. They would may use explicit destruction and placement new instead (and logicaly it is more correct), but assignment has a chance to be more efficient. I suppose, it is logically redundant requirement "to be assignable" (copy constructable is enough), but stl containers want to be faster and simpler.
Of course, it is possible to implement assignment as explicit destruction+placement new to avoid const_cast hack
Rather than declaring the data-member const, you can make the public surface of the class const, apart from the implicitly defined parts that make it (semi)regular.
class Multiply {
public:
Multiply(double coef) : coef(coef) {}
double operator()(double x) const {
return coef*x;
}
private:
double coef;
};
You basically never want to put a const member variable in a class. (Ditto with using references as members of a class.)
Constness is really intended for your program's control flow -- to prevent mutating objects at the wrong times in your code. So don't declare const member variables in your class's definition, rather make it all or nothing when you declare instances of the class.