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.
Related
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.
In the following code, I have a function member and a data member which is a function pointer. For use in a declaration or as a template parameter, the type of a pointer to the function member f is int (Test::*)(int); but what is the analogous type of a pointer to the function pointer data member pf?
struct Test
{
int f( int ) { return 0; };
int (*pf)( int );
};
int main()
{
using Fmem = int (Test::*)( int );
Fmem x = &Test::f;
// using PFmem = ??;
// PFmem y = &Test::pf;
}
using PFmem = int (*Test::*)( int );
// ^ a pointer ...
// ^^^^^^ to a member of Test ...
// ^ which is a pointer ...
// ^ ^ to a function ...
// ^^^ taking an int ...
// ^^^ returning an int
You can also try to untangle the syntax with template typedefs (I'm not sure if it's worth it):
struct Test
{
int f( int ) { return 0; };
int (*pf)( int );
};
template<typename T> using pointer_to = T *;
template<class C, typename T> using pointer_to_member_of = T C::*;
template<typename R, typename ...A> using function = R (A ...);
int main()
{
using Fmem = int (Test::*)( int );
Fmem x = &Test::f;
using PFmem = int (*Test::*)( int );
PFmem y = &Test::pf;
pointer_to_member_of<Test, function<int, int>>
x1 = &Test::f;
pointer_to_member_of<Test, pointer_to<function<int, int>>>
y2 = &Test::pf;
}
struct Test
{
int f( int ) { return 0; };
int (*pf)( int );
};
int main()
{
using Fmem = int (Test::*)( int );
Fmem x = &Test::f;
using PFmem = int (* Test::*)( int );
PFmem y = &Test::pf;
}
If you have doubts you could deduce the type with help of the compiler error message:
using PFmem = int; // any type
PFmem y = &Test::pf;
The code above causes the error message below:
prog.cpp:13:30: error: cannot convert ‘int (* Test::*)(int)’ to ‘int’ in assignment
PFmem y = &Test::pf;
From this error message we now know the required type is int (* Test::*)(int).
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 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 );
}