Using std::bind2nd with references - c++

I have a simple class like this:
class A
{
public:
void f(const int& n)
{
std::cout<<"A::f()" << n <<"\n";
}
};
and I am trying to use it like this:
std::vector<A> vec;
A a;
vec.push_back(a);
std::for_each(vec.begin(), vec.end(), std::bind2nd(std::mem_fun_ref(&A::f), 9));
But when I compile the code I get the following error somewhere inside functional header file:
error C2529: '_Right' : reference to
reference is illegal
If I remove the reference in the parameter f() it compiles fine. How do I resolve this? I don't want to remove the reference as in my real code the copying of the object is quite costly. Also, I am not using boost.

You can't do that easily, sorry. Just consider it one of those cases not covered by std::bind1st and std::bind2nd (kinda like 3-argument functions etc). Boost would help - boost::bind supports references transparently, and there's also boost::ref.
If your implementation supports TR1 - latest g++ versions and VC++2008 SP1 both do - then you can use std::tr1::bind, which is for the most part same as boost::bind, but standardized.

I dont believe you can bind parameters to a method that takes references. (not in the STL, I think the boost versions may let you do it but I am not sure)
You will need to roll your own.
struct CallF
{
CallF(int const& data): m_data(data) {}
void operator()(A& val) const
{
val.f(m_data);
}
int const& m_data;
};
Use like this:
std::for_each(vec.begin(), vec.end(), CallF(9));

I've been bitten by the same problem. If you look into the C++ standard, you'll see that it's actually a "library defect". A conforming C++ implementation simply can't deal with reference parameters. mem_fun_ref returns an object of a class that has nested typedefs (
argument_type, first_argument_type, second_argument_type
) where references are not stripped away. bind1st and bind2nd are specified to have an operator() wich takes references as parameters. In case argument_type is a reference already this will fail to compile.
One solution might be to replace memfunref with your own template magic and strip away references for the nested argument_type typedefs.

Actually, the compilers error message tells the whole story:
error C2529: '_Right' : reference to reference is illegal
std:: binders take their arguments as references - you cant pass a reference to a reference.
No way.

Related

QSet<func pointer> does not compile by gcc

I'm trying to use QSet for storing a list of function pointers. See this code for more details. The problem is that this code does not compile by gcc/mingw. MSVC compiles it normally. What am I doing wrong?
typedef intptr_t (*UikHook)(intptr_t);
...
typedef struct
{
QSet<UikHook>* qsetSubscribers;
//QMutex* qmutexHook;
} THookableEvent;
...
THookableEvent* p = qmapHooks_.value(name);
if (p->qsetSubscribers == 0)
p->qsetSubscribers = new QSet<UikHook>();
p->qsetSubscribers->insert(hookProc);
error: no matching function for call to ‘qHash(long int (* const&)(long int))’
Perhaps, I should to declare operator== and function qHash() for type UikHook as it said in the docs, but I dont know how to do it because when I'm declaring opertator==, I get the following error:
inline bool operator==(const UikHook &e1, const UikHook &e2)
error: ‘bool operator==(intptr_t (* const&)(intptr_t), intptr_t (* const&)(intptr_t))’
must have an argument of class or enumerated type
P.S. I'm using Qt 5.8, gcc 6.2, msvc2015
Update: Solved by replacing QSet to QVector.
You can't define an operator== for built-in types, such as pointers, integers or floating-point numbers. They already have it. You just need to provide a qHash.
Using function pointers is not really the best practice in C++. In early C++ versions, functors were used instead. Since C++11, there are real function objects. You can convert a function pointer to an object via std::function() (Reference).
If the compilers you listed are the ones you need to support, I strongly suggest using std::function instead of function pointers.
Try (warning, brain compile):
template <typename R, typename ...A>
inline uint qHash(R (*)(A...) const f) noexcept
{
return std::hash<R (*)(A...)>()(f);
}
Qt is in a fix here, since it can't use the STL and hashing function pointers is somewhat compiler specific.

Binding overloaded function

This code was developed and originally worked with boost 1.48. Since updating to boost 1.52 it refuses to compile.
boost::signals2::signal<void (uint32_t)> foo;
boost::shared_ptr<boost::circular_buffer<uint32_t>> _foo_buffer = new boost::circular_buffer<uint32_t>(32);
_foo.connect(boost::bind(&boost::circular_buffer<uint32_t>::push_front, _foo_buffer, _1));
The goal is to have foo(42) place 42 on the front of the circular buffer.
My compile error is No matching function for call to 'bind' with a bunch of Candidate template ignored: couldn't infer template argument 'R' and similar template errors.
I suspect the problem is that between the boost versions I'm using, the definition for push_front changed from
void push_front(const_reference item = value_type());
to the three definitions
void push_front(param_value_type);
void push_front(rvalue_type);
void push_front();
and it's confused my compiler.
I would really appreciate some help with the syntax of a connect expression that will work with the new boost library. Thanks
let's say you have the two functions
void foo( int ) {}
void foo( double* ) {}
then you can't just write &foo since that would be ambiguous.
but you can use static_cast to establish a context where only one candidate is possible, thusly:
static_cast<void(*)(int)>( &foo )
which gives you the address of the first one, and ditto for the second one.
that said, it looks like you can simplify things by using a C++ lambda function instead of a bind (for a C++03 compiler alternatively define your own functot).

Automatic binding for boost::thread in C++?

When doing:
std::vector<int> vec;
int number = 4;
boost::thread workerThread(&Method, number, vec)
given a method:
template<typename T>
void Method(int n, std::vector<T> & vec)
{
//does stuff
}
Why do I have to manually do:
boost::thread workerThread(&Method, number, boost::ref(vec))?
Why does it not automatically pass it by reference?
Edit:: so would it be possible theoretically for boost::thread to do some macro-meta-programming to adjust this since C++ has nothing in the way of built in reflection/introspection.
So is a major part of boost / C++ in general passing meta-information around?
Because the boost::thread object cannot determine the signature of Method.
He only knows the types of the arguments being passed in and will forward them to the provided function. If the types don't match you get a nice complicated error message at the place where boost::thread attempts to call the function.
When looking at the types of the arguments, it is impossible to differ between pass-by-reference and pass-by-value as they look the same from the caller's side. Or from a more formal perspective: In template argument deduction T& will decay to T.
Only by providing the explicit boost::ref on the caller's side boost::thread will be able to correctly identify the type as a reference type.
Probably the workerThread might be trying to deduce the types in signaure of Method , which it cant deduce from &Method, itself.

std::function pointer to member function taking rvalue arguement MSVC2010 SP1

I would like to create a std::function bound to a member function taking a rvalue argument. Here is my attempt which does not compile ("xxfunction(154): error C2664: ... You cannot bind an lvalue to an rvalue reference" among others).
class C
{
public:
void F(std::string &&s)
{
//do something with s
}
C(){}
};
C c;
std::function<void(std::string&&)> pF = std::bind(&C::F,&c,std::placeholders::_1);
//somewhere far far away
pF(std::string("test"));
I did some reading and I think it has to do with std::function no using perfect forwarding but I cant figure out how to get it to work.
Edit:
std::function<void(std::string&)> pF = [&c](std::string&in){c.F(std::move(in));};
This is a semi viable work around but it is not perfect because calling pF will work with an lvalue now and move it anyway.
std::string s("test");
pF(s);
auto other = s; //oops
It seems your std::bind implementation does not support perfect forwarding via placeholders, but since you have C++11 and std::bind is ugly anyways, use lambdas:
std::function<void(std::string&&)> pF
= [&c](std::string&& str)
{
c.F(std::move(str));
};
Edit:
Note: Although accepted, this answer is not a solution to the problem at hand, because it is not std::bind but MSVC10's std::function implementation that is flawed. However, the suggestion has led to a workaround and therefore was accepted by PorkyBrain.

How to pass a std::vector to a function by reference with default value being an empty std::vector in C++?

I've been trying to pass a std::vector to a function by reference with default value being an empty std::vector. The declaration of my function looks as follows:
void function( std::vector<double>& vec=std::vector<double>(0));
The definition of my function is:
void function( std::vector<double>& vec)
{
...
}
However my C++ compiler (gcc 4.6) is throwing an error here, saying:
error: default argument for parameter of type ‘std::vector&’ has type ‘std::vector’
I've seen this version of the code compile fine on a Microsoft VS 2010 compiler. And I'm wondering if this is an issue of different c++ standard interpretation between gcc and vs2010.
You can't. You can't bind a temporary to a ref-to-non-const, so you could only do this:
void function(const std::vector<double>& vec = std::vector<double>());
In your case, then, I suggest function overloading:
void function(std::vector<double>& vec)
{
// ...
}
void function()
{
std::vector<double> v;
function(v);
}
If you don't like the extra function call then you're out of luck. :)
I don't know whether C++11 rvalue refs might help here, if you have access to them.
I've seen this version of the code compile fine on a Microsoft VS 2010 compiler. And I'm wondering if this is an issue of different c++ standard interpretation between gcc and vs2010.
MSVS has a tendency to allow you to bind temporaries to refs-to-non-const, which is non-standard behaviour. GCC is correct.
You can do the following:
namespace{
auto empty_vec = std::vector<double>();
}
void function(std::vector<double>& vec=empty_vec);
then you do not have to change the signature of your function. But you have to define the variable empty_vec instead. I put it in an unnamed namespace to make it invisible from outside this translation unit.
But the drawback is (as LightnessRacesinOrbit noted below) that within this translation unit the value of empty_vec can be changed, which might break your function.
You can't pass temporary object as nonconst lvalue-reference!
Add const qualifier or remove default argument.
The following method makes it clear what the default value is -- and it can be replaced with other default behaviors.
static std::vector<double> emptyVectorProvider()
{
return (std::vector<double>());
}
void function (std::vector<double>&& = emptyVectorProvider ());
void function2 (std::vector<double>&& def = emptyVectorProvider ())
{
function(std::forward<std::vector<double> > (def));
}