C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to use generate_n to fill vector<MyInt>, with explicit

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Terry G
Guest





PostPosted: Sun Nov 19, 2006 9:13 am    Post subject: How to use generate_n to fill vector<MyInt>, with explicit Reply with quote



This doesn't quite work.
What is the proper way to do this?
terry

class MyInt {
int _value;
public:
explicit MyInt(int x=0) : _value(x) { }
int value() const { return _value; }
}; // MyInt

int main() {
vector<MyInt> v;

// HOW TO DO THIS USING GENERATE_N?
// for (int i=0; i!=30; ++i) v.push_back(MyInt(rand()));
generate_n(back_inserter(v), 30, bind(MyInt, bind(rand))); // compile
error

// Now print v.
transform(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"),
mem_fn(&MyInt::value));

return 0;
} // main



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Carl Barron
Guest





PostPosted: Sun Nov 19, 2006 10:10 am    Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic Reply with quote



Simplest solution is to provide a function that creates a MyInt
indicated below. Or just use the simple for loop....

In article <ejnupn$k09$1 (AT) news (DOT) netins.net>, Terry G
<tjgolubi (AT) netins (DOT) net> wrote:

Quote:
This doesn't quite work.
What is the proper way to do this?
terry

class MyInt {
int _value;
public:
explicit MyInt(int x=0) : _value(x) { }
int value() const { return _value; }
}; // MyInt


inline make_MyInt() {return MyInt(rand);}

Quote:
int main() {
vector<MyInt> v;

// HOW TO DO THIS USING GENERATE_N?
// for (int i=0; i!=30; ++i) v.push_back(MyInt(rand()));
// generate_n(back_inserter(v), 30, bind(MyInt, bind(rand))); // compile
//error

generate_n(back_inserter(v),30,make_MyInt);

Quote:
// Now print v.
transform(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"),
mem_fn(&MyInt::value));

return 0;
} // main

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
terry
Guest





PostPosted: Sun Nov 19, 2006 10:10 am    Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic Reply with quote



{ Quoted clc++m banner removed. To all new posters: please don't quote
the cl++m banner, and please don't top-post (see FAQ 5.4). -mod/aps }


I would try something like

class wrap

{

int (*myfunc) ();

public:

wrap (int (*func) ()) : myfunc(func){};

MyInt operator()(){return MyInt(myfunc());};

};

................

wrap myrandint(rand);

generate_n(back_inserter(v), 30, myrandint);



and if I were going to do it often I would template wrap.



Dont know if this is useful. Perhaps there is a predefined method available.



Terry





"Terry G" <tjgolubi (AT) netins (DOT) net> wrote in message
news:ejnupn$k09$1 (AT) news (DOT) netins.net...
Quote:
This doesn't quite work.
What is the proper way to do this?
terry

class MyInt {
int _value;
public:
explicit MyInt(int x=0) : _value(x) { }
int value() const { return _value; }
}; // MyInt

int main() {
vector<MyInt> v;

// HOW TO DO THIS USING GENERATE_N?
// for (int i=0; i!=30; ++i) v.push_back(MyInt(rand()));
generate_n(back_inserter(v), 30, bind(MyInt, bind(rand))); // compile
error

// Now print v.
transform(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"),
mem_fn(&MyInt::value));

return 0;
} // main

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Carl Barron
Guest





PostPosted: Sun Nov 19, 2006 10:10 am    Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic Reply with quote

In article <ejoo1j$hd9$1 (AT) news (DOT) netins.net>, Terry G
<tjgolubi (AT) netins (DOT) net> wrote:

Quote:
Carl Barron wrote:
Simplest solution is to provide a function that creates a MyInt
indicated below. Or just use the simple for loop....

inline make_MyInt() {return MyInt(rand());}

Really?
With all the hype about avoiding implicit conversions, I thought there must
be an easier way.
I think a simple conversion template function would suffice, say
explicit_cast.
Something like this, then?

class MyInt {
int _value;
public:
explicit MyInt(int x=0) : _value(x) { }
int value() const { return _value; }
}; // MyInt

template <typename R, typename T
inline R explicit_cast(const T& x) { return R(x); }
.....
generate_n(back_inserter(v), 30, bind(explicit_cast<MyInt, int>,
bind(rand)));

should work the same, remember you are now passing a function

returning a MyInt with an int argument rather than a type. I did not
bother with the tempated approach to keep the example code simple...
That is the essential difference between a working solution and the
original.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Greg Herlihy
Guest





PostPosted: Sun Nov 19, 2006 10:10 am    Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic Reply with quote

Terry G wrote:
Quote:
Carl Barron wrote:
Simplest solution is to provide a function that creates a MyInt
indicated below. Or just use the simple for loop....

inline make_MyInt() {return MyInt(rand());}

Really?
With all the hype about avoiding implicit conversions, I thought there must
be an easier way.

The easiest way would be to allow the implicit conversion from an int
to MyInt by removing the "explicit" qualifier from MyInt's constructor:

class MyInt {
int _value;
public:
MyInt(int x=0) : _value(x) { }
int value() const { return _value; }
};

Now the solution becomes quite straightforward:

vector<MyInt> v;

generate_n( back_inserter(v), 30, rand);

Greg


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Terry G
Guest





PostPosted: Sun Nov 19, 2006 10:10 am    Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic Reply with quote

Carl Barron wrote:
Quote:
Simplest solution is to provide a function that creates a MyInt
indicated below. Or just use the simple for loop....

inline make_MyInt() {return MyInt(rand());}

Really?
With all the hype about avoiding implicit conversions, I thought there must
be an easier way.
I think a simple conversion template function would suffice, say
explicit_cast.
Something like this, then?

class MyInt {
int _value;
public:
explicit MyInt(int x=0) : _value(x) { }
int value() const { return _value; }
}; // MyInt

template <typename R, typename T>
inline R explicit_cast(const T& x) { return R(x); }

int main() {
vector<MyInt> v;
// for (int i=0; i!=30; ++i) v.push_back(MyInt(rand()));
generate_n(back_inserter(v), 30, bind(explicit_cast<MyInt, int>,
bind(rand)));
transform(v.begin(), v.end(),
ostream_iterator<int>(cout, "\n"),
mem_fn(&MyInt::value));
return 0;
} // main

terry




--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Terry G
Guest





PostPosted: Mon Nov 20, 2006 10:10 am    Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic Reply with quote

Quote:
The easiest way would be to allow the implicit conversion from an int
to MyInt by removing the "explicit" qualifier from MyInt's constructor:

Experts agree: implicit conversions are to be avoided.
I've been bitten by this a few times too.

But the STL doesn't work as spiffily when one uses explicit constructors.
So far, the explicit_cast<> solution seems to be the best method to handle
this problem.

terry



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Greg Herlihy
Guest





PostPosted: Tue Nov 21, 2006 1:57 am    Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic Reply with quote

Terry G wrote:
Quote:
The easiest way would be to allow the implicit conversion from an int
to MyInt by removing the "explicit" qualifier from MyInt's constructor:

Experts agree: implicit conversions are to be avoided.
I've been bitten by this a few times too.

Those experts must not be the same experts who designed the C++
language or its Standard Library - both of which routinely use implicit
conversion where it makes sense to do so. But whatever their
differences over implicit conversions, both sets of experts are likely
to agree on at least one point: that a blanket rule, uncritically
applied without regard to the particulars of the situation - is
definitely a practice to avoid.

It stands to reason that implicit conversions must be useful for
something - or why would the C++ language support them? Moreover, if
ever there is a time for implicit conversion, one would think that that
an int to a class object representing an integer value would be that
occasion. Especially since the built-in integer types all implicitly
convert among themselves. A C++ programmer expects that, say, the value
3 can be used as an unsigned long parameter. But without implicit
conversion, passing 3 as an unsigned long would be an error. The
program would instead have to specify 3UL as the argument - and would
have gained little benefit in exchange for the additional
inconvenience.

Furthermore, the experts' advice has been over-generalized. It's not
the implicit converstion to the class type that is likely to cause as
many problems as an implicit conversion from the user-defined class to
a built-in type. The Standard Library string class is a good
case-in-point. A C++ program can pass a string literal whenever a const
std::string argument is expected thanks to implicit conversion. The C++
programmer is spared the hassle of specifying std::string("some
string") when the programmer's intention is obvious. Yet there is no
corresponding std::string-to-char-pointer implicit conversion, because
such a conversion could cause problems. The std::tr1::shared_ptr
follows the same practice: a pointer implicitly converts to a
shared_ptr but a shared_ptr does not implicitly convert to a pointer.

Quote:
But the STL doesn't work as spiffily when one uses explicit constructors.
So far, the explicit_cast<> solution seems to be the best method to handle
this problem.

Not necessarily. If implicit conversion is still off limits, then there
is always the possiblity of assignment. Is it permissible to assign a
MyInt class object an int value? If so, then the following solution is
possible:

class MyInt
{
int _value;
public:
explicit MyInt(int x=0) : _value(x) { }

MyInt& operator=(const int& rhs)
{
_value = rhs;
return *this;
}
int value() const { return _value; }
}; // MyInt

...
vector<MyInt> v(30);

generate( v.begin(), v.end(), rand );

Greg


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Terry G
Guest





PostPosted: Wed Nov 22, 2006 9:08 am    Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic Reply with quote

The MyInt class that encapsulates an int was just a simple example of a more
complex problem.
I was only interested in how to invoke a conversion when using generic
algorithms.

A generic explicit_cast template function, boost lambda constructor, or a
helper function will all do the trick.

Thanks!
terry



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.