 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Terry G Guest
|
Posted: Sun Nov 19, 2006 9:13 am Post subject: How to use generate_n to fill vector<MyInt>, with explicit |
|
|
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
|
Posted: Sun Nov 19, 2006 10:10 am Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic |
|
|
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
|
Posted: Sun Nov 19, 2006 10:10 am Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic |
|
|
{ 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
|
Posted: Sun Nov 19, 2006 10:10 am Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic |
|
|
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
|
Posted: Sun Nov 19, 2006 10:10 am Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic |
|
|
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
|
Posted: Sun Nov 19, 2006 10:10 am Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic |
|
|
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
|
Posted: Mon Nov 20, 2006 10:10 am Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic |
|
|
| 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
|
Posted: Tue Nov 21, 2006 1:57 am Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic |
|
|
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
|
Posted: Wed Nov 22, 2006 9:08 am Post subject: Re: How to use generate_n to fill vector<MyInt>, with explic |
|
|
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 |
|
 |
|
|
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
|
|