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.
Related
I want to hold some structures Data in a vector. These structures reference other ones by indices (instead of pointers), to conserve memory and make serialization easier. To follow these indices, I created a class DataView, which provides a comfortable interface for it. It looks like this:
#include <iostream>
#include <vector>
struct Data
{
int id_next;
int id_prev;
int value;
};
class Foo;
class DataView
{
Foo * foo;
int index;
public:
DataView( Foo * foo_, int index_ )
: foo( foo_ ), index( index_ )
{
}
DataView next() const;
DataView prev() const;
int value() const;
int & value();
int id() const
{
return index;
}
};
class Foo
{
std::vector<Data> data;
public:
friend class DataView;
DataView dataview( int index )
{
return DataView( this, index );
}
Foo()
{
data.resize( 5 );
for ( int i = 0; i < (int)data.size(); i++ )
{
data[i].id_next = (i + 1) % data.size();
data[i].id_prev = (i + 4) % data.size();
data[i].value = i * i;
}
}
void write_cycle( int start_index ) // const
{
DataView seek = dataview( start_index );
do
{
std::cout << "index " << seek.id() << " value " << seek.value() << std::endl;
seek = seek.next();
} while ( seek.id() != start_index );
}
};
DataView DataView::next() const
{
return DataView( foo, foo->data[index].id_next );
}
DataView DataView::prev() const
{
return DataView( foo, foo->data[index].id_prev );
}
int DataView::value() const
{
return foo->data[index].value;
}
int & DataView::value()
{
return foo->data[index].value;
}
int main()
{
Foo foo;
foo.write_cycle( 3 );
foo.dataview( 2 ).value() = 11;
foo.write_cycle( 3 );
return 0;
}
The problem arises if I have to differentiate between const and non-const variations of dataview method. In fact, write_cycle should be const, as it doesn't change anything. However, I get compiler error if I uncomment const qualifier.
error: passing ‘const Foo’ as ‘this’ argument discards qualifiers [-fpermissive]
How to write DataView containing const or non-const foo pointer, depending on whether its constructor was called with const or non-const pointer?
You said:
These structures reference other ones by indices (instead of pointers), to conserve memory and make serialization easier. To follow these indices, I created a class DataView, which provides a comfortable interface for it.
That indicates to me that you should not need to support:
foo.dataview( 2 ).value() = 11;
Use DataView to only read the data. If you agree with that, you can change DataView to store a Foo const*. You can then get rid of the non-const version of DataView::value().
class DataView
{
Foo const* foo;
int index;
public:
DataView( Foo const* foo_, int index_ )
: foo( foo_ ), index( index_ )
{
}
DataView next() const;
DataView prev() const;
int value() const;
// Don't need this.
// int & value();
int id() const
{
return index;
}
};
If a method is const, then nothing it does or provides can be be allowed to change the instance. This includes any functions or other methods the method calls, and references to any members that the method returns must be const so they can't be used to modify the object in the future.
So if write_cycle is const then dataview must be const and DataView must have a constructor that accepts const Foo *. And this means DataView::foo must also be const to accept assignment of a const Foo *. This could be a problem if DataView's clients expect to manipulate the stored Foo.
End result, write_cycle can't be const without a bunch of extra work.
To add to user R Sahu's answer about leaving Foo within Dataview as const since it will act as a read only class and shouldn't modify Foo; you can add this function into Foo's class to update its values:
void Foo::updateValue( int index, const int& value ) {
if ( index < 0 || index >= data.size() ) {
return;
}
data[index].value = value;
}
Then inside of your main.cpp file would look like this:
Foo foo;
std::cout << "writing cycle of 3" << std::endl;
foo.write_cycle( 3 );
std::cout << "updating index 2 with value of 11" << std::endl;
foo.updateValue( 2, 11 );
std::cout << "writing cycle of 3" << std::endl;
foo.write_cycle( 3 );
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();
}
}
I'm trying to understand why the following code doesn't compile.
class X
{
public:
template< typename T >
void set( T & val )
{
}
};
int main( int c, char *v[] )
{
X x;
x.set( new int( 99 ) ); // 15
}
On my solaris compiler I get the following error.
"x.cpp", line 15: Error: Could not find a match for X::set<X::T>(int*) needed in main(int, char**).
I can't work out why the compiler woudln't take the reference of a pointer to an int and pass the type "T" as "int *"
It can, but that's a temp ;)
class X
{
public:
template< typename T >
void set( T const & val ) // add const here
{
}
};
and you can't bind it to a non-const reference.
Same reason why this would work:
class X
{
public:
template< typename T >
void set( T & val )
{
}
};
int main( int c, char *v[] )
{
X x;
int * y = new int( 99 );
x.set( y ); // 15
}
here, y is no longer a temporary.
The result of the new expression is an rvalue, so it cannot bind to a non-const reference.
Declare your template as void set(T val) instead to pass the pointer by value.
You can not bind a temporary to a non-const reference.
If you need to preserve that method's signature, you need to create a variable, and pass it to that method :
class X
{
public:
template< typename T >
void set( T & val )
{
}
};
int main( int c, char *v[] )
{
X x;
int * p = new int( 99 );
x.set( p ); // 15
}
If you can change method's signature, pass the parameter by either const reference, or by value.
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
}
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 );
}