C++ initialize priority_queue with custom compare function - c++

I have a Dijkstra class which uses a priority_queue with a custom compare function. I named the queue DijkstraPriorityQueue with a using statement. Inside the class constructor, I initialize the queue. To do that, I give the compare function in a lambda expression.
For the first queue, PQ1, the compare function is { return distTo[u] > distTo[v]; } and this compiles fine, because the vector<float> distTo is a member of the class.
But for the second queue, PQ2, the function is { return distTo2[u] > distTo2[v]; } where vector<float> distTo2 is just a temporary variable inside the constructor, and that doesn't compile. (I think that's the reason at least)
Also, I randomly tried to change vector<float> distTo2 to static vector<float> distTo2 by intuition and it compiles, however I don't think this is what I want to be doing. I am not familiar with static variables inside functions, since that doesn't exist in Java or C#. At any case, what is a clean solution to make the code below compile and work as intended ?
Dijkstra.h
class Dijkstra
{
public:
Dijkstra();
~Dijkstra();
private:
vector<float> distTo;
};
Dijkstra.cpp
using DijkstraPriorityQueue = priority_queue<int, vector<int>, function<bool(int, int)>>;
Dijkstra::Dijkstra()
{
distTo = vector<float>(V, FLT_MAX);
// Compiles fine
DijkstraPriorityQueue PQ1 = DijkstraPriorityQueue([this](int u, int v)
{ return distTo[u] > distTo[v]; });
vector<float> distTo2 = vector<float>(V, FLT_MAX);
// Doesn't compile
DijkstraPriorityQueue PQ2 = DijkstraPriorityQueue([this](int u, int v)
{ return distTo2[u] > distTo2[v]; });
}
Edit:
The following code compiles too. Any clues why ? Can someone explain what capture is on lambda expressions ? Or how should I write my code properly in this specific case ?
DijkstraPriorityQueue PQ2 = DijkstraPriorityQueue([distTo2](int u, int v)
{ return distTo2[u] > distTo2[v]; });

There are two main aspects of your question:
What is this “capture” thing, and why the error?
How to specify a custom compare function for a priority queue?
These aspects are most cleanly discussed separately.
Unfortunately the presented (incomplete) example code is not well suited for discussing either aspect, so I just disregard it.
What is a lambda capture.
Consider the following code:
#include <stdio.h>
struct S
{
int a_;
void foo() const
{
// Compiles nicely:
[this]() -> void { printf( "%d\n", a_ ); }();
// Doesn't compile, oh why!:
int b = 666;
[this]() -> void { printf( "%d\n", b ); }();
}
};
auto main()
-> int
{ S{ 42 }.foo(); }
MinGW g++ 5.1.0 provides the following diagnostics (compilation errors):
x1.cpp: In lambda function:
x1.cpp:14:44: error: 'b' is not captured
[this]() -> void { printf( "%d\n", b ); }();
^
x1.cpp:14:14: note: the lambda has no capture-default
[this]() -> void { printf( "%d\n", b ); }();
^
x1.cpp:13:13: note: 'int b' declared here
int b = 666;
^
To understand the “not captured”, let's implement the lambdas manually, just doing a code transformation equivalent to what the compiler does with it:
void foo() const
{
// Compiles nicely:
//[this]() -> void { printf( "%d\n", a_ ); }();
class Functor_a
{
private:
S const* captured_this_;
public:
void operator()()
{ printf( "%d\n", captured_this_->a_ ); }
Functor_a( S const* this_capture )
: captured_this_( this_capture )
{}
};
Functor_a f_a{ this };
f_a();
// Doesn't compile, oh why!:
int b = 666;
// [this]() -> void { printf( "%d\n", b ); }();
class Functor_b
{
private:
S const* captured_this_;
public:
void operator()()
{ printf( "%d\n", b ); }
Functor_b( S const* this_capture )
: captured_this_( this_capture )
{}
};
Functor_b f_b{ this };
f_b();
}
};
The diagnostic is now more clear. Since Functor_b is a class, and since a class in C++ is completely free-standing entity, its code has no relation to or access to things in a particular invocation of foo(). So the compiler doesn't accept the reference to some unspecified b, but notes that if you really meant the b in the containing scope, then hey, that name b refers to a different variable in each call of foo, and isn't a valid choice:
x2.cpp: In member function 'void S::foo() const::Functor_b::operator()()':
x2.cpp:37:35: error: use of local variable with automatic storage from containing function
{ printf( "%d\n", b ); }
^
x2.cpp:28:17: note: 'int b' declared here
int b = 666;
^
One solution is to capture the value, i.e. copy it into the functor class instance, e.g. as follows:
class Functor_b
{
private:
int const captured_b_;
public:
void operator()()
{ printf( "%d\n", captured_b_ ); }
Functor_b( int const b_capture )
: captured_b_( b_capture )
{}
};
Functor_b f_b{ b }; // ← The capture.
f_b(); // ← Using the captured value.
Alternatively you could capture a pointer to the variable, capture by reference. In that the case the pointer is only valid for the lifetime of the variable. So you'd better not keep a functor instance around after that.
Expressed in lambda notation the capture of the value can look like this:
[b]() -> void { printf( "%d\n", b ); }();
Or like this, with a general capture-whatever's-needed-by-value =:
[=]() -> void { printf( "%d\n", b ); }();
Capturing by reference, i.e. a pointer, looks like this:
[&]() -> void { printf( "%d\n", b ); }();
How to specify a compare function for a std::priority_queue.
E.g. like this:
#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;
struct S
{
string name;
int birth_year;
};
auto main() -> int
{
struct Age_sort
{
auto operator()( S const& a, S const& b )
-> bool
{ return (a.birth_year < b.birth_year); }
};
using Q = priority_queue< S, vector<S>, Age_sort >;
Q pq;
pq.push( S{ "beta", 1980 } );
pq.push( S{ "alfa", 1992 } );
pq.push( S{ "charlie", 1971 } );
while( not pq.empty() )
{
cout << pq.top().name << ' ' << pq.top().birth_year << endl;
pq.pop();
}
}

Related

how to pass a bitfield in by reference

Note a question with nearly the exact same title already exists, but is asking a very different question.
Say I want a method that takes a bitfield reference or pointer as an argument. This isn't legal, but perhaps an example would clarify:
class Foo {
unsigned a:2, b:2, c:2;
bool Bar( unsigned* px:2 ) { *px = a; return true; };
}
Foo foo;
if ( foo.Bar( &foo.b ) )
exit( EXIT_SUCCESS );
I could write Bar as a macro:
#define BAR( pfoo, field ) ( ( (pfoo)->field = (pfoo)->a ), true )
Foo foo;
if ( BAR( &foo, b ) )
exit( EXIT_SUCCESS );
Many place where you'd write some such macro in C you can now handle with function templates. Is there a template solution to writing the above Bar() method legally in C++11 or later?
It is possible to cobble up something that acts as a bitfield reference in a rather inefficient and roundabout way.
template<typename underlying>
struct bitfield_ref
{
virtual underlying get() { return getter(); }
virtual void set(underlying val) { setter(val); }
bitfield_ref(std::function<underlying()> getter, std::function<void(underlying)> setter) :
getter(getter), setter(setter) {}
std::function<underlying()> getter;
std::function<void(underlying)> setter;
};
#define BITFIELD_REF(s,m) bitfield_ref<decltype(s.m)>( \
[&s]() { return s.m; }, \
[&s](decltype(s.m) v) { s.m = v; })
It can be used this way
struct moo
{
unsigned int a : 2;
unsigned int b : 3;
};
unsigned int test(bitfield_ref<unsigned int> x)
{
x.set(3);
return x.get() + 1;
}
int main()
{
moo m;
std::cout << test(BITFIELD_REF(m, a)) << "\n";
}
It is further possible to get rid of get and set by defining a conversion operator and an assignment operator (and all of the compound assignments to go with it), this is omitted for brevity.

How can a lambda capture itself for an asynchronous call?

I have to make an asynchronous call inside a lambda, and once the asynchronous call is terminated I have to call the lambda itself.
I try to explain my problem with code:
typedef function<void(int id)> Callback;
AsyncWork1(Callback call, int id, string)
{
//...
call(id);
}
AsyncWork2(Callback call, int id, double, string)
{
//...
call(id);
}
void AsyncWorks(Callback final_callback, int id)
{
Callback lambda = [&lambda, final_callback, id](int next_work) -> void
{
if(next_work == 1)
{
//...
AsyncWork1(lambda, 2, "bla bla");
}
else if(next_work == 2)
{
//...
//the lambda variable no longer exists
AsyncWork2(lambda, 3, 0.0, "bla bla");
}
else if(next_work == 3)
{
//...
final_callback(id);
}
};
lambda(1);
}
int main()
{
AsyncWorks(...);
AsyncWorks(...);
AsyncWorks(...);
AsyncWorks(...);
return 0;
}
The problem is that when the code exits from "AsyncWorks(...)" function, the local variable "lambda" no longer exists.
I've read several threads that talk about lambda recursive, but I haven't found any solution.
How can I solve this problem?
The basic problem is that C++ doesn't expose the this pointer of a lambda to itself.
As it happens, there are many languages where during something's definition, you cannot refer to itself. This is fixed in functional languages using a technique called the "Y Combinator".
A simple y combinator in C++ looks like:
template<class F>
struct y_combinator_t {
F f;
template<class...Args>
auto operator()(Args&&...args)
-> std::result_of_t< F&( y_combinator_t<F>&, Args&&... ) >
{
return f( *this, std::forward<Args>(args)... );
}
};
template<class F>
y_combinator_t<std::decay_t<F>> y_combinate( F&& f ) {
return {std::forward<F>(f)};
}
I'm of two minds if we should f( *this or f( f, I sometimes do either.
Use:
void AsyncWorks(Callback final_callback, int id)
{
Callback lambda = y_combinate(
[final_callback, id]
(auto& self, int next_work)
-> void
{
if(next_work == 1) {
//...
AsyncWork1(self, 2, "bla bla");
} else if(next_work == 2) {
//...
//the lambda variable no longer exists
AsyncWork2(self, 3, 0.0, "bla bla");
} else if(next_work == 3) {
//...
final_callback(id);
}
}
);
lambda(1);
}
basically, I added an implicit self parameter to the lambda function body. Caller of the operator() don't see this parameter.
Y combinator based off this post by myself with modifications.
Lambda can capture itself implicitly. To demo how? see below code it calculate factorial value.
#include <iostream>
int (* factorial)( const int) = []( const int number)
{
if( number > 1)
{
return number* factorial( number - 1);
}
else
{
return 1;
}
};
int main(int , char *[])
{
int fact = factorial( 7);
std::cout<< "7! = "<< fact<< std::endl;
}
Output 7! = 5040
If any variable is used inside lambda then lambda captures it implicitly, if it is not captured explicitly. Due to this inside lambda, name factorial referring itself, is available.
But if in place ofint (* factorial)( const int) = []( const int number){//implementation }; if auto is used like as follows,auto factorial = []( const int number){ //implementation };then g++ compiler gives following error,error: use of ‘factorial’ before deduction of ‘auto’
return number* factorial( number - 1);It is because type of factorial is not deduced, auto does not deduce for same control block. Name factorial will be available only below the declaration in case of auto.
#Yakk
To understand your answer I had to spend some time studying many c++ features, value category, rvalue, lvalue, move constructor, move assignment operator, variadic templates, variadic templates with implicit conversions, result_of_t<>, decay_t<>, forward<>.
But I don't have a thing yet, why did you put the '&' symbol here?
... std::result_of_t <F&(y_combinator_t<...
I also rewrote your solution to make it more specific for my case and easier to read and understand for me too (and for all those who are beginners with C++),
class y_combinator_t
{
public:
function<void(y_combinator_t*, int, double, string)> callback;
void operator()(int a, double b, string s)
{
this->callback(this, a, b, s);
}
};
y_combinator_t combinator = {
[id_work = 1]
(y_combinator_t* _this, int a, double b, string s) mutable -> void
{
if(id_work == 1)
{
//...
AsyncWork1(*_this, 2, 3.0, "bla bla");
id_work = 2;
}
else if(id_work == 2)
{
//...
AsyncWork2(*_this, 3, 0.0, "bla bla");
id_work = 3;
}
else if(id_work == 3)
{
//...
}
}
};
//Start works
combinator(0, 0, "");

Can a range-based for loop take a type argument?

From what I can tell, range-based for loops can only take a c-style array, an object of a type that has the member functions begin() and end() defined, or an object of a type Type for which the free functions begin(Type) and end(Type) can be found with ADL.
Is there a way to make the loop take a type argument, so code like this compiles?
class StaticVec{
//shortened implementation
static myIterator begin();
static myIterator end();
};
void foo() {
for(auto elem : StaticVec){
dosomething(elem);
}
}
I would like to omit the necessity of writing StaticVec::values() in the loop.
As a general solution you can define
template< class Type > struct Static_collection {};
template< class Type >
auto begin( Static_collection<Type> const& )
-> decltype( Type::begin() )
{ return Type::begin(); }
template< class Type >
auto end( Static_collection<Type> const& )
-> decltype( Type::end() )
{ return Type::end(); }
and then you can write e.g.
auto main() -> int
{
for( auto elem : Static_collection<Static_vec>() )
{
std::cout << elem << ' ';
}
std::cout << '\n';
}
Addendum:
In most practical cases it will however suffice to just create an instance of the class holding the static begin and end member functions, as shown in Jarod42’s and Matt McNabb’s answers (the former already posted when I posted the above), e.g.
for( auto const& elem : StaticVec() )
{
// ...
}
If instance creation can have undesirable side effects, now or perhaps after some future maintainance work, then use the general solution.
Otherwise, if instance creation is essentially free, I’d go for that.
You may still (if applicable) construct a dummy object:
for (auto&& elem : StaticVec{}) {
// ...
}
It's definitely not possible. The range variable in your example is StaticVec (which is not a variable) so the code it expands to would involve either auto it = StaticVec.begin() or auto it = begin(StaticVec) and neither of those expressions is valid, the function calls require an object not a type.
This works because static member functions can still be called via . notation:
#include <iostream>
using namespace std;
struct StaticVec
{
typedef int *myIterator;
static int x[5];
static myIterator begin() { return x; }
static myIterator end() { return x + 5; }
};
int StaticVec::x[5] = { 10, 20, 30, 40, 50 };
void dosomething(int i)
{
cout << i << endl;
}
int main()
{
for(auto elem : StaticVec())
{
dosomething(elem);
}
}

Pass a member function to create a free function boost pointer

I try to get this code running. I am almost there but I got stuck with the line:
_f = std::bind1st(
std::mem_fun(f, x);
First of all please understand that I don't want to change any code, but the constructor. Why? Because I want to learn. Eventually I want to write a wrapper class Func, that can handle free functions and member function at the same time, in this very manner.
So what wuld I have to put as the first argument inside the std::mem_func()-call???
I tried numerous things.
Probably this is a duplicate, but I don't know how to search for this problem. I lack the vocabulary. If someone can point to a tutorial or something, that would help me to express this problem, I would also appreciate it.
Here is the full sample code:
#include <boost/function.hpp>
#include <iostream>
struct X
{
int foo(int i)
{
return i;
};
};
class Func
{
public:
Func(X *x, int (X::* f) (int))
{
_f = std::bind1st(
std::mem_fun(f, x);
std::cout << _f(5); // Call x.foo(5)
};
private:
boost::function<int (int)> _f;
};
int main()
{
X x;
Func func(&x, &X::foo);
return 0;
}
Thanks in advance.
It seems you just forgot a paren:
_f = std::bind1st(std::mem_fun(f), x);
Although I would initialize with
Func(X *x, int (X::* f) (int))
: _f(std::bind1st(std::mem_fun(f), x))
{
std::cout << _f(5); // Call x.foo(5)
};
(It doesn't matter in this case, but this style is safer in the long run.)
I would refactor the class slightly to use boost::function in the interface, and then the user can decide how to bind in the most generic way:
struct X {
int foo(int i) { return i; };
};
class Func {
boost::function<int (int)> _f;
public:
Func( boost::function<int (int)> f ){
_f = f;
std::cout << _f(5);
};
};
int foo( int x ) { return 2*x; }
int bar( int x, int multiplier ) { return x*multiplier; }
int main() {
X x;
Func func1( boost::bind( &X::foo, &x, _1 ) ); // this does the magic
Func func2( boost::bind( &foo, _1 ) ); // you can also bind free functions...
Func func3( boost::bind( &bar, _1, 5 ) ); // or with different arguments
}

Using std::vector<T*>::push_back with std::mem_fun and std::bind1st

I'm trying to use std::vector<T*>::push_back with std::mem_fun and std::binder1st, but it doesnt seem to be feasible, can this be done?
I've tried to exemplify with the code below.
#include <vector>
#include <functional>
#include <iostream>
using namespace std;
struct A {
int _Foo;
virtual int AFoo() { return _Foo; };
};
struct B: public A {
int BFoo(int bar) { return _Foo+bar ; };
};
struct C: public A {
int CFoo() { return --_Foo; };
};
class MyContainer
{
static const int MyArraySize = 100;
A* MyArray[MyArraySize];
public:
MyContainer() {
int half = MyArraySize / 2;
for( int i=0; i< half; ++i )
MyArray[i] = new B;
for( int i=half; i < MyArraySize; ++i )
MyArray[i] = new C;
}
template<class T, class Fn1>
int Execute( Fn1 func )
{
int count = 0;
for( int i=0; i< MyArraySize; ++i ){
T* t = dynamic_cast<T*>(MyArray[i]);
if( t )
{
func(t);
++count;
}
}
return count;
}
template<class T, class Res, class Arg>
int Execute( mem_fun1_t<Res, T, Arg> func, Arg argument )
{
return Execute<T>( binder2nd< mem_fun1_t<Res,T,Arg> >( func, argument ) );
}
template<class T>
vector<T*> GetItems() // <-- This is the problem function
{
vector<T*> ret;
Execute<T>( bind1st( mem_fun(&vector<T*>::push_back), ret ) );
return ret;
}
};
int main( int argc, char* argv[] )
{
MyContainer cont;
cont.Execute<B>( mem_fun(&B::BFoo), 10 );
cont.Execute<C>( mem_fun(&C::CFoo) );
vector<B*> v = cont.GetItems<A>(); // <-- the problem function is called here.
cout << "v.size = " << v.size() << endl;
}
My goal is to have a container class to which I can tell it to execute a function receiving the selected items ('A' objects or 'A' derivate objects) as parameters. But I didn't manage to use std::vector::push_pack with it.
The problem is that binder1st defines operator() as:
operator() (const typename Operation::second_argument_type& x) const
and mem_fun1_t defines operator() as:
S operator() (T* p, A x) const
The problem is that push_back is defined as:
void vector<T>::push_back(const T &x)
So what we end up with is this:
void mem_fun1_t::operator()(vector<T *> *p, const T *&x)
And:
void binder1st::operator()(const T *&&x)
In other words, a reference to a reference to a pointer. A reference to a reference doesn't exist in C++. The only decent way I can think of fixing this is to use boost::bind instead:
vector<T*> ret;
Execute<T>( boost::bind( mem_fun(&vector<T*>::push_back), &ret, _1) );
return ret;
Also note that you had a bug, and need to pass bind &ret instead of just ret (as mem_fun expects a pointer, mem_fun_ref would work however).
The easiest way to call member functions on the entire set of items in your container is to use for_each:
using namespace std;
using namespace std::tr1;
vector<T> cont;
// ...
for_each( cont.begin(), cont.end(),
bind( &T::foo, 42 ) );
// assume void T::foo(int); exists
If you don't have tr1 you can use:
for_each( cont.begin(), cont.end(),
bind2nd( mem_fun( &s::foo ), 42 ) // first parameter is the object itself
);
I am not sure what you are trying to achieve here though. You have both compile time polymorphism (aka templates) and runtime polymorphism (aka virtual member functions). The design seems a bit too complicated. In fact the following definition suffices:
int Execute()
{
int count = 0;
for( int i=0; i< MyArraySize; ++i ){
MyArray[ i ]->Foo(); // assume virtual int A::Foo(); exists
++count;
}
return count;
}
However, as you may have found out, virtual members need to have the same signature in order to be overriden in sub-classes (otherwise you are overloading the function).
Note that the sample GetItems does not call a member function of the contained objects, it calls a member, namely, push_back on the vector container object.
If all you want to do is to copy the pointers from a vanilla array to a vector you could use vector's specialized ctor that takes two iterators:
template<class T>
vector<T*> GetItems() // <-- This is the problem function
{
return vector<T*>( &MyArray[ 0 ], &MyArray[ 0 ] + MyArraySize );
}