Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > error: passing `const ...' as `this' argument of `...' discardsqualifiers

Reply
Thread Tools

error: passing `const ...' as `this' argument of `...' discardsqualifiers

 
 
Giovanni Gherdovich
Guest
Posts: n/a
 
      08-12-2008
Hello,

I'm doing some toy experiments to see how
the algoritm std::transform and the function
adapter std::bind2nd can play together, but
my compiler give my the error

error: passing `const traslate' as `this' argument of
`circle traslate:perator()(circle, std::vector<double,
std::allocator<double> >)'
discards qualifiers

It should be like I'm trying to modify
something which is declared as const...

The example code follows.

I define the type `circle', which holds
center and radius of a circle, then I
introduce a vector of circles and try to
traslate them all with std::transform.
I need std::bind2nd to fix the traslation
for all the circles.
Note that I'm forced to define the
temporary object `traslate' to meet
std::bind2nd input specifications.

// =======================================
#include <vector>
#include<functional>
#include<algorithm>
using namespace std;

struct circle
{
vector<double> center;
double radius;
};

struct traslate
{
typedef circle first_argument_type;
typedef vector<double> second_argument_type;
typedef circle result_type;
circle operator()(const circle original, const vector<double>
traslation)
{
circle traslated = original;
traslated.center[0] += traslation[0];
traslated.center[1] += traslation[1];
return traslated;
}
};

int main()
{
vector<circle> lots_of_circles(10);
vector<circle> some_other_circles(10);
vector<double> traslation(2);
traslation[0] = 123;
traslation[1] = 321;
transform(lots_of_circles.begin(), lots_of_circles.end(),
some_other_circles.begin(), bind2nd(traslate(), traslation));
}
// =======================================

Can you see the reason of the above mentioned error?

Regards,
Giovanni Gh.
 
Reply With Quote
 
 
 
 
mlimber
Guest
Posts: n/a
 
      08-12-2008
On Aug 12, 9:23*am, Giovanni Gherdovich
<(E-Mail Removed)> wrote:
> Hello,
>
> I'm doing some toy experiments to see how
> the algoritm std::transform and the function
> adapter std::bind2nd can play together, but
> my compiler give my the error
>
> error: passing `const traslate' as `this' argument of
> `circle traslate:perator()(circle, std::vector<double,
> std::allocator<double> >)'
> discards qualifiers
>
> It should be like I'm trying to modify
> something which is declared as const...
>
> The example code follows.
>
> I define the type `circle', which holds
> center and radius of a circle, then I
> introduce a vector of circles and try to
> traslate them all with std::transform.
> I need std::bind2nd to fix the traslation
> for all the circles.
> Note that I'm forced to define the
> temporary object `traslate' to meet
> std::bind2nd input specifications.
>
> // =======================================
> #include <vector>
> #include<functional>
> #include<algorithm>
> using namespace std;
>
> struct circle
> {
> * vector<double> center;


How about std:air instead? Or, perhaps even better, make your own
point class with members x and y. std::vector is overkill here.

> * double radius;
>
> };
>
> struct traslate
> {
> *typedef circle first_argument_type;
> *typedef vector<double> second_argument_type;
> *typedef circle result_type;


Consider inheriting from std::binary_function instead of this.

> *circle operator()(const circle original, const vector<double>
> traslation)


You probably want to use references for both of these parameters to
prevent unnecessary copies. (They may be inlined away or relatively
trivial here, but maybe not if you call this a lot.) You should also
use std:air or your own point class here, too, since you only have x
and y coordinates. Since this function doesn't modify the object's
state, it should be made const (note also the references):

circle operator()(
const circle& original,
const vector<double>& traslation) const
{ ... }

However, since your functor has no state, you should just make this a
plain old function rather than a function object.

> *{
> * *circle traslated = original;
> * *traslated.center[0] += traslation[0];
> * *traslated.center[1] += traslation[1];
> * *return traslated;
> *}
>
> };
>
> int main()
> {
> * vector<circle> lots_of_circles(10);
> * vector<circle> some_other_circles(10);
> * vector<double> traslation(2);
> * traslation[0] = 123;
> * traslation[1] = 321;
> * transform(lots_of_circles.begin(), lots_of_circles.end(),
> some_other_circles.begin(), bind2nd(traslate(), traslation));}
>
> // =======================================
>
> Can you see the reason of the above mentioned error?


You're creating a temporary object -- the instance of translate --
which is bound to a const reference in bind2nd. The function you are
calling is not const. Add const to the member function, or better,
make it a plain old function.

See these FAQs for more info on const-correctness:

http://www.parashift.com/c++-faq-lit...rrectness.html

Cheers! --M
 
Reply With Quote
 
 
 
 
Giovanni Gherdovich
Guest
Posts: n/a
 
      08-12-2008
Thank you; you answer even more than
what I've asked and I appreciate it a lot.

> > struct circle
> > {
> > vector<double> center;

>
> How about std:air instead


I agree. And since I don't need any method
for these points, std:air will do the job.

> > struct traslate
> > {
> > typedef circle first_argument_type;
> > typedef vector<double> second_argument_type;
> > typedef circle result_type;

>
> Consider inheriting from std::binary_function
> instead of this.


Cool!
So I can avoid to explicitly rename my types with the
tedious

typedef circle first_argument_type;
typedef vector<double> second_argument_type;
typedef circle result_type;

> However, since your functor has no state, you should just make this a
> plain old function rather than a function object.


True, but if I do that I cannot use the algorithm std::tranform,
wich save me from looping explicitly over the circles (wich I
find is cool), because I cannot use std::bind2nd
(which wants a function object as first argument).

> You're creating a temporary object -- the instance of translate --
> which is bound to a const reference in bind2nd. The function you are
> calling is not const. Add const to the member function


Exactly.
Thank you, also for the reference to the FAQs.

But let me understand: std::bind2nd onbly accept _const_ member
functions a input function object?

Cheers,
Giovanni
 
Reply With Quote
 
mlimber
Guest
Posts: n/a
 
      08-12-2008
On Aug 12, 10:57*am, Giovanni Gherdovich
<(E-Mail Removed)> wrote:
> > How about std:air instead

>
> I agree. And since I don't need any method
> for these points, std:air will do the job.


Right, though struct Point { double x,y; }; may make your code easier
to read and only requires reinventing a very, very small wheel.

> > However, since your functor has no state, you should just make this a
> > plain old function rather than a function object.

>
> True, but if I do that I cannot use the algorithm std::tranform,
> wich save me from looping explicitly over the circles (wich I
> find is cool), because I cannot use std::bind2nd
> (which wants a function object as first argument).


With ordinary functions, just use std:tr_fun to wrap them for
std::transform et al.:

circle Translate1( const circle original, const vector<double>
traslation)
{ /* code from traslate:perator() */ }

// ...
transform(lots_of_circles.begin(), lots_of_circles.end(),
some_other_circles.begin(),
bind2nd(ptr_fun(Translate), traslation));

You may notice I omitted the references from the parameters to
Translate1 because, unfortunately, the standard binders currently
don't allow reference arguments. For more on this problem, see
http://www.boost.org/doc/libs/1_35_0...raits.htm#refs

Alternately, if you have the standard library extensions known as TR1
or if you have Boost (where most of those extensions originated), you
could use reference arguments with the generalized binder
(std::tr1::bind or boost::bind) instead of std::bind2nd:

// Note ref params
circle Translate2( const circle& original, const vector<double>&
traslation)
{/*same code*/}

// ...

// TR1 version
transform(lots_of_circles.begin(), lots_of_circles.end(),
some_other_circles.begin(),
std::tr1::bind(
Translate2,
std::tr1:laceholders::_1,
traslation) );

// Easier-to-read version of the above:
using namespace std::tr1;
using namespace std::tr1:laceholders;

transform(lots_of_circles.begin(), lots_of_circles.end(),
some_other_circles.begin(), bind( Translate2, _1, traslation) );


// Boost version
transform(lots_of_circles.begin(), lots_of_circles.end(),
some_other_circles.begin(), boost::bind(Translate2, _1,
traslation) );

For more on these, see Pete Becker's article:

http://www.ddj.com/cpp/184401949

or his book on TR1, or the Boost.Bind documentation.

> But let me understand: std::bind2nd onbly accept _const_ member
> functions a input function object?


Yes. The enhanced binders correct this and other "inconveniences" with
the standard binders.

Cheers! --M
 
Reply With Quote
 
Giovanni Gherdovich
Guest
Posts: n/a
 
      08-13-2008
Dear Mlimber,

> > > However, since your functor has no state, you should just make this a
> > > plain old function rather than a function object.

> >
> > True, but if I do that I cannot use the algorithm std::tranform,
> > wich save me from looping explicitly over the circles (wich I
> > find is cool), because I cannot use std::bind2nd
> > (which wants a function object as first argument).

>
> With ordinary functions, just use std:tr_fun to wrap them for
> std::transform et al.:


this information is precious.
I was wondering how to use std::bind2nd without building
ad-hoc function object...

> You may notice I omitted the references from the parameters to
> Translate1 because, unfortunately, the standard binders currently
> don't allow reference arguments. For more on this problem, see
> http://www.boost.org/doc/libs/1_35_0...raits.htm#refs
>
> Alternately, if you have the standard library extensions known as TR1
> or if you have Boost


Mmmh... I was not aware of that.
I may have to review my design, or to use Pete Becker's TR1 or Boost
as you suggest.
The point is that I have to call a code analogous to the circles'
one...
a few millions of times.
And as you told,

> You probably want to use references for both of these parameters to
> prevent unnecessary copies. (They may be inlined away or relatively
> trivial here, but maybe not if you call this a lot.)


I will study this issue.

Cheers,
Giovanni
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to use a passing argument(returned argument)? ؿ Ruby 7 11-27-2008 03:53 AM
Passing a function as an argument and using the evaluated functionas an argument User1014 Javascript 1 11-30-2006 12:13 PM
Argument-per-argument Passing Trans Ruby 3 01-26-2005 05:58 PM
How to pass variable argument list to another function w/ variable argument list? Ben Kial C Programming 1 11-15-2004 01:51 AM
defaulting argument to previous argument Bhushit Joshipura C++ 5 12-30-2003 03:21 PM



Advertisments