reference to reference and constness problems with bind1st

M

Marc

T x;
T foo(T, T);
bind1st(ptr_fun(foo), x)

creates a function object that takes an argument of type T const&. This
does not work if T is already a reference type like int const&. So my
first problem is with the &. My second problem is with the const. Why
should bind1st change the constness of the second argument of the
function ?

I am currently using boost::bind instead, but I would rather not depend
on boost for all my programs...
 
D

Denis Remezov

Marc said:
T x;
T foo(T, T);
bind1st(ptr_fun(foo), x)

creates a function object that takes an argument of type T const&. This
does not work if T is already a reference type like int const&. So my
first problem is with the &. My second problem is with the const. Why
should bind1st change the constness of the second argument of the
function ?

If instead of bind1st(Op const& op, T const& y) we had
bind1st(Op const& op, T& y), it would cause a problem deducing a
const reference template argument when used with, e.g. a temporary
or a numeric literal:
bind1st(ptr_fun(foo), 13);

The deduced type of template parameter T would be int, not const int,
T& would not bind to the argument, and the above would fail to compile.

I am currently using boost::bind instead, but I would rather not depend
on boost for all my programs...

You could change the parameters of foo from references to pointers.

When I was experimenting with this problem (and couldn't use boost)
I came up with a rather uncouth alternative of duplicating the standard
bind1st for the case when the template parameters are references (I've
never used it for real though):

template <class Op>
class refbinder1st : public unary_function<typename Op::second_argument_type,
typename Op::result_type> {
protected:
Op op_;
typename Op::first_argument_type val_;
public:
refbinder1st(const Op& op,
const typename Op::first_argument_type val) : op_(op),
val_(val) {}
typename Op::result_type operator ()(
const typename Op::second_argument_type arg) const {
return op_(val_, arg);
}
};

// Both arguments of Op should be references or very small objects
template <class Op, typename T>
refbinder1st<Op> refbind1st(const Op& op, T v_1st) {
return refbinder1st<Op>(op, typename Op::first_argument_type(v_1st));
}


Denis
 
T

tom_usenet

T x;
T foo(T, T);
bind1st(ptr_fun(foo), x)

creates a function object that takes an argument of type T const&. This
does not work if T is already a reference type like int const&. So my
first problem is with the &. My second problem is with the const. Why
should bind1st change the constness of the second argument of the
function ?

Just the way it is written. Perfect argument passing is an unsolved
problem of C++, although the next version of the standard is going to
address it I think. In the absense of perfect argument passing, old
code used const references. Some new code uses more sophisticated
schemes, such as the call_traits in boost, or even rvalue/lvalue/const
resolving stuff (e.g. Mojo).
I am currently using boost::bind instead, but I would rather not depend
on boost for all my programs...

Boost contains too much essential stuff not to depend on it. I'd just
end up rewriting half of it if I couldn't use it. However, you can
just lift out the <boost/functional.hpp> header for a replacement
<functional> header that works much better.

Tom
 
M

Marc

Denis said:
If instead of bind1st(Op const& op, T const& y) we had
bind1st(Op const& op, T& y), it would cause a problem deducing a
const reference template argument when used with, e.g. a temporary
or a numeric literal:
bind1st(ptr_fun(foo), 13);

The deduced type of template parameter T would be int, not const int,
T& would not bind to the argument, and the above would fail to compile.

I thought that it could be overloaded with a const and a non-const
versions. But I don't have time to check.
When I was experimenting with this problem (and couldn't use boost)
I came up with a rather uncouth alternative of duplicating the standard
bind1st for the case when the template parameters are references (I've
never used it for real though):

That is interesting, and it seems to work fine. Thank you for your
answer.
 
M

Marc

tom_usenet said:
Just the way it is written. Perfect argument passing is an unsolved
problem of C++, although the next version of the standard is going to
address it I think.

Do you have a reference on this "perfect argument passing" issue ?
Boost contains too much essential stuff not to depend on it. I'd just
end up rewriting half of it if I couldn't use it. However, you can
just lift out the <boost/functional.hpp> header for a replacement
<functional> header that works much better.

Cool, I had not seen this in boost. I hope the next standard benefits
from it.

Thank you for your answer.
 
T

tom_usenet

D

Denis Remezov

Marc said:
I thought that it could be overloaded with a const and a non-const
versions. But I don't have time to check.

Yes, but the problem is the automatic template parameter deduction:

template <typename T>
void f(T& v) {
}

int main() {
const int a=13;
f(a); //all right

f<int const>(13); //all right as well

f(13); //error
}

Denis
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top