PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.cplus > Why does transform() needs a struct and an operator()?
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
Why does transform() needs a struct and an operator()?

Réponse
 
LinkBack Outils de la discussion
Vieux 11/12/2007, 00h24   #1
Alex Buell
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Why does transform() needs a struct and an operator()?

I've just written the below as an exercise (don't worry about the lack
of checking), but I was wondering why I needed to write a struct with
an operator() as a parameter to supply to the STL transform() function?

#include <algorithm>
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
#include <string>
#include <cctype>

using namespace std;

struct lowercase
{
string operator()(const string& s)
{
string lower(s);

for (size_t i = 0; i < s.length(); ++i)
lower[i] = tolower(lower[i]);

return lower;
}
};

int main(int argc, char* argv[])
{
if (argc > 1)
{
ifstream in(argv[1]);
vector<string> vs;

copy(istream_iterator<string>(in),
istream_iterator<string>(), back_inserter(vs)); transform(vs.begin(),
vs.end(), vs.begin(), lowercase()); sort(vs.begin(), vs.end());

vector<string>::iterator it = unique(vs.begin(), vs.end
()); vs.resize(it - vs.begin());

copy(vs.begin(), vs.end(), ostream_iterator<string>
(cout, "\n")); }
}


--
http://www.munted.org.uk

Fearsome grindings.
  Réponse avec citation
Vieux 11/12/2007, 01h28   #2
Kai-Uwe Bux
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Why does transform() needs a struct and an operator()?

Alex Buell wrote:

> I've just written the below as an exercise (don't worry about the lack
> of checking), but I was wondering why I needed to write a struct with
> an operator() as a parameter to supply to the STL transform() function?


You don't.


> #include <algorithm>
> #include <iostream>
> #include <fstream>
> #include <iterator>
> #include <vector>
> #include <string>
> #include <cctype>
>
> using namespace std;
>
> struct lowercase
> {
> string operator()(const string& s)
> {
> string lower(s);
>
> for (size_t i = 0; i < s.length(); ++i)
> lower[i] = tolower(lower[i]);
>
> return lower;
> }
> };
>
> int main(int argc, char* argv[])
> {
> if (argc > 1)
> {
> ifstream in(argv[1]);
> vector<string> vs;
>
> copy(istream_iterator<string>(in),
> istream_iterator<string>(), back_inserter(vs)); transform(vs.begin(),
> vs.end(), vs.begin(), lowercase()); sort(vs.begin(), vs.end());
>
> vector<string>::iterator it = unique(vs.begin(), vs.end
> ()); vs.resize(it - vs.begin());
>
> copy(vs.begin(), vs.end(), ostream_iterator<string>
> (cout, "\n")); }
> }


Consider:

#include <algorithm>
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
#include <string>
#include <cctype>

using namespace std;

string lowercase ( string const s ) {
string lower(s);
for (size_t i = 0; i < s.length(); ++i) {
lower[i] = tolower(lower[i]);
}
return lower;
}

int main(int argc, char* argv[]) {
if (argc > 1) {
ifstream in(argv[1]);
vector<string> vs;

copy(istream_iterator<string>(in),
istream_iterator<string>(),
back_inserter(vs));
transform(vs.begin(), vs.end(), vs.begin(), &lowercase);
sort(vs.begin(), vs.end());

vector<string>::iterator it =
unique(vs.begin(), vs.end());
vs.resize(it - vs.begin());

copy(vs.begin(), vs.end(),
ostream_iterator<string>(cout, "\n")); }
}


Now, which way is better in which ways is a different matter.


Best

Kai-Uwe Bux
  Réponse avec citation
Vieux 11/12/2007, 01h29   #3
Victor Bazarov
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Why does transform() needs a struct and an operator()?

Alex Buell wrote:
> I've just written the below as an exercise (don't worry about the lack
> of checking), but I was wondering why I needed to write a struct with
> an operator() as a parameter to supply to the STL transform()
> function?


You didn't. You could just write it as a stand-alone function.
Less typing, and you wouldn't need the () after it when calling
'transform'.

Tty it

string lowercase(const string& s)
{
... // your implementation
}

....
transform(vs.begin(), vs.end(), vs.begin(), lowercase);

>
> #include <algorithm>
> #include <iostream>
> #include <fstream>
> #include <iterator>
> #include <vector>
> #include <string>
> #include <cctype>
>
> using namespace std;
>
> struct lowercase
> {
> string operator()(const string& s)
> {
> string lower(s);
>
> for (size_t i = 0; i < s.length(); ++i)
> lower[i] = tolower(lower[i]);
>
> return lower;
> }
> };
>
> int main(int argc, char* argv[])
> {
> if (argc > 1)
> {
> ifstream in(argv[1]);
> vector<string> vs;
>
> copy(istream_iterator<string>(in),
> istream_iterator<string>(), back_inserter(vs)); transform(vs.begin(),
> vs.end(), vs.begin(), lowercase()); sort(vs.begin(), vs.end());
>
> vector<string>::iterator it = unique(vs.begin(), vs.end
> ()); vs.resize(it - vs.begin());
>
> copy(vs.begin(), vs.end(), ostream_iterator<string>
> (cout, "\n")); }
> }


V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


  Réponse avec citation
Vieux 11/12/2007, 09h26   #4
Alex Buell
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Why does transform() needs a struct and an operator()?

On Mon, 10 Dec 2007 20:28:37 -0500, I waved a wand and this message
magically appears in front of Kai-Uwe Bux:

> string lowercase ( string const s ) {
> string lower(s);
> for (size_t i = 0; i < s.length(); ++i) {
> lower[i] = tolower(lower[i]);
> }
> return lower;
> }


Thanks, I did just that when writing the exercise, but the compiler
wouldn't accept it - I know why now - it doesn't need the () when
calling a function. For operator () functions, it does need the ().
Thanks for pointing out the differences!

Thanks also to Bazarov!

Regards,
Alex
--
http://www.munted.org.uk

Fearsome grindings.
  Réponse avec citation
Vieux 11/12/2007, 09h37   #5
mathieu
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Why does transform() needs a struct and an operator()?

On Dec 11, 2:28 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> Alex Buell wrote:
> > I've just written the below as an exercise (don't worry about the lack
> > of checking), but I was wondering why I needed to write a struct with
> > an operator() as a parameter to supply to the STL transform() function?

>
> You don't.
>
>
>
> > #include <algorithm>
> > #include <iostream>
> > #include <fstream>
> > #include <iterator>
> > #include <vector>
> > #include <string>
> > #include <cctype>

>
> > using namespace std;

>
> > struct lowercase
> > {
> > string operator()(const string& s)
> > {
> > string lower(s);

>
> > for (size_t i = 0; i < s.length(); ++i)
> > lower[i] = tolower(lower[i]);

>
> > return lower;
> > }
> > };

>
> > int main(int argc, char* argv[])
> > {
> > if (argc > 1)
> > {
> > ifstream in(argv[1]);
> > vector<string> vs;

>
> > copy(istream_iterator<string>(in),
> > istream_iterator<string>(), back_inserter(vs)); transform(vs.begin(),
> > vs.end(), vs.begin(), lowercase()); sort(vs.begin(), vs.end());

>
> > vector<string>::iterator it = unique(vs.begin(), vs.end
> > ()); vs.resize(it - vs.begin());

>
> > copy(vs.begin(), vs.end(), ostream_iterator<string>
> > (cout, "\n")); }
> > }

>
> Consider:
>
> #include <algorithm>
> #include <iostream>
> #include <fstream>
> #include <iterator>
> #include <vector>
> #include <string>
> #include <cctype>
>
> using namespace std;
>
> string lowercase ( string const s ) {
> string lower(s);
> for (size_t i = 0; i < s.length(); ++i) {
> lower[i] = tolower(lower[i]);
> }
> return lower;
>
> }
>
> int main(int argc, char* argv[]) {
> if (argc > 1) {
> ifstream in(argv[1]);
> vector<string> vs;
>
> copy(istream_iterator<string>(in),
> istream_iterator<string>(),
> back_inserter(vs));
> transform(vs.begin(), vs.end(), vs.begin(), &lowercase);
> sort(vs.begin(), vs.end());
>
> vector<string>::iterator it =
> unique(vs.begin(), vs.end());
> vs.resize(it - vs.begin());
>
> copy(vs.begin(), vs.end(),
> ostream_iterator<string>(cout, "\n")); }
>
> }
>
> Now, which way is better in which ways is a different matter.


Is there actually any difference at all (if we except the passing by
copy in your implementation) ?

Thanks
-Mathieu
  Réponse avec citation
Vieux 11/12/2007, 10h26   #6
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Why does transform() needs a struct and an operator()?

On Dec 11, 10:37 am, mathieu <mathieu.malate...@gmail.com> wrote:
> On Dec 11, 2:28 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> > Alex Buell wrote:
> > > I've just written the below as an exercise (don't worry about the lack
> > > of checking), but I was wondering why I needed to write a struct with
> > > an operator() as a parameter to supply to the STL transform() function?


> > You don't.


[...]
> > string lowercase ( string const s ) {
> > string lower(s);
> > for (size_t i = 0; i < s.length(); ++i) {
> > lower[i] = tolower(lower[i]);
> > }
> > return lower;
> > }


> > int main(int argc, char* argv[]) {
> > if (argc > 1) {
> > ifstream in(argv[1]);
> > vector<string> vs;


> > copy(istream_iterator<string>(in),
> > istream_iterator<string>(),
> > back_inserter(vs));
> > transform(vs.begin(), vs.end(), vs.begin(), &lowercase);
> > sort(vs.begin(), vs.end());


> > vector<string>::iterator it =
> > unique(vs.begin(), vs.end());
> > vs.resize(it - vs.begin());


> > copy(vs.begin(), vs.end(),
> > ostream_iterator<string>(cout, "\n")); }
> > }


> > Now, which way is better in which ways is a different matter.


> Is there actually any difference at all (if we except the
> passing by copy in your implementation) ?


One small difference: if you use a functional object, each
different function has a different type, so the compiler will
have to generate a distinct instantiation of the transform
function template for each different function you pass. All of
the pointers to function have the same type, so there is only
one instantiation.

Note that this means that with the functional object, the
compiler may be able to inline the function, and even if it
doesn't, it is a call to a fixed address, not through an
indirection. So you may get slightly more speed in return for
the code bloat.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
  Réponse avec citation
Vieux 11/12/2007, 13h00   #7
mathieu
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Why does transform() needs a struct and an operator()?

On Dec 11, 11:26 am, James Kanze <james.ka...@gmail.com> wrote:
> On Dec 11, 10:37 am, mathieu <mathieu.malate...@gmail.com> wrote:
>
> > On Dec 11, 2:28 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> > > Alex Buell wrote:
> > > > I've just written the below as an exercise (don't worry about the lack
> > > > of checking), but I was wondering why I needed to write a struct with
> > > > an operator() as a parameter to supply to the STL transform() function?
> > > You don't.

>
> [...]
>
>
>
> > > string lowercase ( string const s ) {
> > > string lower(s);
> > > for (size_t i = 0; i < s.length(); ++i) {
> > > lower[i] = tolower(lower[i]);
> > > }
> > > return lower;
> > > }
> > > int main(int argc, char* argv[]) {
> > > if (argc > 1) {
> > > ifstream in(argv[1]);
> > > vector<string> vs;
> > > copy(istream_iterator<string>(in),
> > > istream_iterator<string>(),
> > > back_inserter(vs));
> > > transform(vs.begin(), vs.end(), vs.begin(), &lowercase);
> > > sort(vs.begin(), vs.end());
> > > vector<string>::iterator it =
> > > unique(vs.begin(), vs.end());
> > > vs.resize(it - vs.begin());
> > > copy(vs.begin(), vs.end(),
> > > ostream_iterator<string>(cout, "\n")); }
> > > }
> > > Now, which way is better in which ways is a different matter.

> > Is there actually any difference at all (if we except the
> > passing by copy in your implementation) ?

>
> One small difference: if you use a functional object, each
> different function has a different type, so the compiler will
> have to generate a distinct instantiation of the transform
> function template for each different function you pass. All of
> the pointers to function have the same type, so there is only
> one instantiation.
>
> Note that this means that with the functional object, the
> compiler may be able to inline the function, and even if it
> doesn't, it is a call to a fixed address, not through an
> indirection. So you may get slightly more speed in return for
> the code bloat.


Thanks !

-Mathieu
  Réponse avec citation
Vieux 12/12/2007, 09h47   #8
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Why does transform() needs a struct and an operator()?

On Dec 11, 1:24 am, Alex Buell <alex.bu...@munted.org.uk> wrote:
> I've just written the below as an exercise (don't worry about
> the lack of checking), but I was wondering why I needed to
> write a struct with an operator() as a parameter to supply to
> the STL transform() function?


Since no one has mentioned it yet...

[...]
> struct lowercase
> {
> string operator()(const string& s)
> {
> string lower(s);


> for (size_t i = 0; i < s.length(); ++i)
> lower[i] = tolower(lower[i]);


This line, of course, results in undefined behavior on
implementations where plain char is signed. If you insist on
using the functions in <cctype> (instead of those in
<locale>---admittedly much more awkward), then you must cast:

lower[ i ] = tolower( static_cast< unsigned char >( lower[ i ] ) ;

And the usual reminder that this doesn't work in all (or even
most) languages: there's not always a one to one mapping of
lower to upper, or vice versa.

> return lower;
> }
> };


--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 11h36.


Édité par : vBulletin® version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,23304 seconds with 16 queries