Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Memberfunktion als STL-Prädikatfunktion

5 views
Skip to first unread message

Joachim Puhr

unread,
Aug 3, 2009, 1:00:37 PM8/3/09
to
Hallo,

wie kann ich eine Memberfunktion eines Objekts (welches einer Funktion
als Pointer �bergeben wurde) als Pr�dikatfunktion eines STL -Aufrufs
verwenden?
Beispiel
struct S {...};
class A {
//...
bool filter(S s) {...}
};

void fn(A* obj)
{
vector <S> v1,v2;
// Die folgende Zeile kompiliert nicht wg. obj->filter
remove_copy_if ( v1.begin( ), v1.end( ), v2.begin( ), obj->filter);
}

Viele Gr��e

Joachim

Sebastian Waschik

unread,
Aug 4, 2009, 6:41:06 PM8/4/09
to
Hallo,

"Joachim Puhr" <jpuhr_re...@gmx.de> writes:
> wie kann ich eine Memberfunktion eines Objekts (welches einer Funktion

> als Pointer ᅵbergeben wurde) als Prᅵdikatfunktion eines STL -Aufrufs
> verwenden?

schaue dir mal das Template mem_fun aus <functional> an.

Viele Grᅵᅵe
Sebastian Waschik

Falk Tannhäuser

unread,
Aug 5, 2009, 4:34:44 AM8/5/09
to
Joachim Puhr wrote:
> struct S {...};
> class A {
> //...
> bool filter(S s) {...}
> };
>
> void fn(A* obj)
> {
> vector <S> v1,v2;
> // Die folgende Zeile kompiliert nicht wg. obj->filter
> remove_copy_if ( v1.begin( ), v1.end( ), v2.begin( ), obj->filter);

std::remove_copy_if(v1.begin(), v1.end(),
std::back_inserter(v2),
// oder v2.begin(), wenn schon genug Platz in v2 ist
std::bind1st(std::mem_fun(&A::filter), obj));

> }

MfG
Falk

Lars Tetzlaff

unread,
Aug 5, 2009, 4:29:32 AM8/5/09
to
Joachim Puhr schrieb:

> Hallo,
>
> wie kann ich eine Memberfunktion eines Objekts (welches einer Funktion
> als Pointer ᅵbergeben wurde) als Prᅵdikatfunktion eines STL -Aufrufs
> verwenden?
Mit Boost (www.boost.org)
> Beispiel
#include <boost/bind.hpp>

> struct S {...};
> class A {
> //...
> bool filter(S s) {...}
> };
>
> void fn(A* obj)
> {
> vector <S> v1,v2;
> // Die folgende Zeile kompiliert nicht wg. obj->filter
> remove_copy_if ( v1.begin( ), v1.end( ), v2.begin( ), obj->filter);
remove_copy_if ( v1.begin( ), v1.end( ), v2.begin( ), boost::bind(
&A::filter, obj, _1 ) );


Lars

SG

unread,
Aug 4, 2009, 7:08:55 PM8/4/09
to
On 3 Aug., 19:00, "Joachim Puhr" <jpuhr_removeth...@gmx.de> wrote:
> Hallo,
>
> wie kann ich eine Memberfunktion eines Objekts (welches einer Funktion
> als Pointer übergeben wurde) als Prädikatfunktion eines STL -Aufrufs

> verwenden?
>
> Beispiel
> struct S {...};
> class A {
> //...
> bool filter(S s) {...}
> };
>
> void fn(A* obj)
> {
> vector <S> v1,v2;
> // Die folgende Zeile kompiliert nicht wg. obj->filter
> remove_copy_if ( v1.begin( ), v1.end( ), v2.begin( ), obj->filter);
> }

Eventuell ist statt v2.begin() ein std::back_inserter(v2) sinnvoller
(siehe <iterator> Header). Ansonsten läufst Du Gefahr, über das Ende
hinaus zu schreiben.

Das Prädikat müsstest Du über std::mem_fun und std::bind1st
hinbekommen:
std::bind1st(std::mem_fun(&A::filter),&obj)
(siehe <functional> Header)

Mit std::tr1::bind bzw boost::bind geht das auch noch einfacher:
bind(&A::filter,&obj,_1);

Gruß,
SG

Björn Hendriks

unread,
Aug 5, 2009, 7:02:55 AM8/5/09
to
Joachim Puhr wrote:

Eine nichtstatische Elementfunktion kann nicht unmittelbar als Prädikat für
einen STL-Algorithmus benutzt werden.

Die einfachste Lösung wäre, A::filter static zu machen, falls das möglich
ist.

Wenn das nicht geht, da A::filter Daten aus dem zugehörigen Objekt braucht,
musst du ein Funktionsobjekt benutzen, also eine Klasse, die eine passende
Elementfunktion operator() (S &) enthält. Im folgenden (ungetesteten!)
Beispiel habe ich das Funktionsobjekt in die Klasse A geschachtelt, damit
der obige Aufruf mit obj->filter weiterhin funktioniert:

class A
{
public:
class TheFilter
{
public:
bool operator() (const S &s) const // ggf. auch ohne const
{
// investigate s --> bool result
return result;
}
} filter;
};

Wahrscheinlich musst du A::TheFilter noch mit passenden Konstruktoren
ausrüsten, da sie keinen direkten Zugriff auf die anderen Elemente von A
hat, solange du kein friend benutzt. Ich persönlich vermeide friend, da es
die Kapselung untergräbt und weiß daher nicht, ob das hier sinnvoll sein
könnte.

Natürlich kannst du TheFilter auch gleich komplett außerhalb von A
definieren und im Konstruktor einen Zeiger oder eine Referenz auf A
übergeben. Dann müsstest du oben anstelle von obj->filter so etwas wie
TheFilter(obj) an remove_copy_if übergeben und einen passenden Konstuktor
bereitstellen.

Gruß
Björn

Olaf Krzikalla

unread,
Aug 5, 2009, 7:02:10 AM8/5/09
to
Hallo,

Joachim Puhr schrieb:


> wie kann ich eine Memberfunktion eines Objekts (welches einer Funktion

> als Pointer ᅵbergeben wurde) als Prᅵdikatfunktion eines STL -Aufrufs


> verwenden?
> Beispiel
> struct S {...};
> class A {
> //...
> bool filter(S s) {...}
> };
>
> void fn(A* obj)
> {
> vector <S> v1,v2;
> // Die folgende Zeile kompiliert nicht wg. obj->filter
> remove_copy_if ( v1.begin( ), v1.end( ), v2.begin( ), obj->filter);
> }

// wenn TR1 nicht vefᅵgbar ist:
//#include <boost/tr1/functional>
#include <functional>

//...

void fn(A* obj)
{
//...
remove_copy_if (v1.begin(), v1.end(), v2.begin(),
std::tr1::bind(&A::filter, obj, std::tr1::placeholders::_1));
}

Das sollte es tun. Den Adress-Operator kannst Du AFAIK auch bei jedem
aktuellen Compiler weglassen. Und beachte die kleinen Fallstricke am
Rande: obiges geht nur so einfach, weil obj ein Pointer ist. Informiere
Dich also auch ᅵber std::tr1::ref.

MfG
Olaf Krzikalla

Christian Freund

unread,
Aug 5, 2009, 5:46:01 AM8/5/09
to
Hallo!

Das habe ich schonmal probiert und aus Interesse gerade nocheinmal. Ohne
boost habe ich es bisher nie hinbekommen. Das Problem ist, das eine
stl-algorithm-funktion wohl nur zul�sst, auch mit STL-binder, das eine
Elementfunktion oder ein Funktor verwendet wird. Wenn es noch anders geht,
ohne boost, dann m�chte ich das auch wissen.

So geht es:

#include "boost/functional.hpp"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"

struct S
{
public:
S () : x(-1) {}
S (int x_in) :x(x_in){}
int x;
};
class A
{
int b;
public:
bool filter(S s)
{
return s.x > 9;
}
};


int main()
{
using namespace std;
using namespace boost::lambda;
A * obj = new A;
std::vector<S> v1,v2(10);
v1.push_back(S(12));
v1.push_back(S(1));
v1.push_back(S(6));
std::remove_copy_if(v1.begin(), v1.end(), v2.begin(), bind(&A::filter, obj,
_1));
[...]

"Joachim Puhr" <jpuhr_re...@gmx.de> schrieb im Newsbeitrag
news:4a7717b4$0$31866$9b4e...@newsspool3.arcor-online.net...

Joachim Puhr

unread,
Aug 5, 2009, 2:38:27 PM8/5/09
to
Vielen Dank f�r alle Antworten, das hat mir sehr weitergeholfen.

Joachim

0 new messages