[c++] optinales funktor/funktionspointer argument

OP #2798229
Lesenswert?
• ▲
▼
Hi, ich habe eine Template Klasse mit einer Memberfunktion Funktion, die 
als optionalen Parameter einen Funktor oder Funtionszeiger haben soll.


ich möchte also hinterher

entweder
process(var)
oder
process(var, Funktor())
oder
process(var, &funktion)
 aufrufen können

wie hat das auszusehen?
Bisher hab ich das getrennt implementiert:
1
#include <iostream>
2
#include <string>
3
using namespace std;
4

5
template <class A, class B>
6
class C
7
{
8
public:
9

10
  static string  printNothing()   {return "";}
11

12
  template < typename ProcessFunctorType>
13
  void process(int i, ProcessFunctorType& pfunc)
14
  {
15
    cout << i << " "<<pfunc()<<endl;
16
  }
17

18
  // diese funktion hätte ich gerne weg, so dass standardmäßig die 
19
  // andere mit printNothing aufgerufen wird.
20
  void process(int i){
21
    cout << i << " "<<endl;
22
  }
23
  
24
  A a;
25
  B b;
26
};
27

28
static string  printSomething() {return "foo";}
29

30
int main()
31
{
32
  C<int, int> c;
33
  c.process(1);
34
  c.process(2, C<int, int>::printNothing);
35
  c.process(3, printSomething);
36

37
}
Da ich aber noch einen weiteren funktor hinzufügen möchte, explodiert 
die Variantenanzahl und ich würde das gerne vereinheitlichen

Hat jemand eine Idee?

hier zum direkten ausprobieren:
http://codepad.org/Pkh944rz

Gruß
Vlad
Gast #2798504
Lesenswert?
• ▲
▼
Ich habe nicht so viel Ahnung und habe es auch nicht ausprobiert, aber 
vielleicht so:
1
template < typename ProcessFunctorType>
2
  void process(int i, ProcessFunctorType& pfunc = NULL)
3
  {
4
    cout << i << " "<<pfunc()<<endl;
5
  }
Gast #2798655
Lesenswert?
• ▲
▼
Vlad Tepesch schrieb:
> Rolf schrieb:
>> http://ladedu.com/cpp/src_html/standard
>
> was will uns der poster damit sagen?
>
> Rolf schrieb:
>> Ich habe nicht so viel Ahnung und habe es auch nicht ausprobiert, aber
>> vielleicht so:
>
> die andern sachen gehen natürlich auch nicht.
>
> weder darf man einer referenz NULL zuweisen, noch wird der defaultwert
> bei templates beachtet

Das geht prinzipiell schon, es muss allerdings eher so aussehen:
1
#include <iostream>
2
#include <string>
3
using namespace std;
4

5
static string  printSomething() {return "foo";}
6

7

8
template <class A, class B>
9
class C
10
{
11
public:
12

13
  static string  printNothing()   {return "";}
14

15
  template < typename ProcessFunctorType =  string () >
16
  void process(int i, ProcessFunctorType &pfunc = printNothing)
17
  {
18
      cout << i << " " <<pfunc()<<endl;
19
  }
20

21

22
//  void process(int i){
23
//    cout << i << " "<<endl;
24
//  }
25

26
  A a;
27
  B b;
28
};

Ausgabe:
1
1 
2
2 
3
3 foo

Default template Argumente bei Funktionstemplates gibt es allerdings 
erst ab C++11.

(kompiliert mit gcc 4.6 und -std=c++0x)
OP #2798742
Lesenswert?
• ▲
▼
ich schrieb:
> Das geht prinzipiell schon, es muss allerdings eher so aussehen:
hmm - den default  template parameter verstehe ich nicht.
müsste es nicht irgendwie "string (*)()" oder so heißen, weil ja der 
Templateparameter ein Funktionspointer ist.

kompiliert er denn auch noch sowas:
1
class TestFunctor{
2
public:
3
  TestFunctor(const string& s)
4
  : m_s(s)
5
  {}
6

7
  string operator()(){
8
    return m_s;
9
  }
10

11
private:
12
  string m_s;
13
};
14

15
///...
16

17
  TestFunctor tf("hallo");
18
  c.process(4, tf );

könnte mir vorstellen, dass es hier Probleme gibt, da der Typ das 
Defaultarguments ( string (*)() ) nicht zum Templatetyp (TestFunctor) 
passt.

kannst du das mal durch deinen Compiler jagen?

Das Codepad und mein MSVC können das nicht
Gast #2798763
Lesenswert?
• ▲
▼
Vlad Tepesch schrieb:
> kannst du das mal durch deinen Compiler jagen?

[23:07:22] <rolf@SL510-Fedora.fritz.box> ~/cpp ((Linux 
3.5.2-1.fc17.x86_64))
1 processes #55 $ g++ -std=c++11 beispiel2.cpp -o beispiel2
[23:09:49] <rolf@SL510-Fedora.fritz.box> ~/cpp ((Linux 
3.5.2-1.fc17.x86_64))
1 processes #56 $ ./beispiel2
1
2
3 foo
4 hallo


macht er ohne zu meckern.

Starte mal eine Linux-Live-Session entweder vom USB-Stick oder von einer 
CD, dann kannst Du das auch selber testen.
Gast #2798794
Lesenswert?
• ▲
▼
Vlad Tepesch schrieb:
> hmm - den default  template parameter verstehe ich nicht.
> müsste es nicht irgendwie "string (*)()" oder so heißen, weil ja der
> Templateparameter ein Funktionspointer ist.

Da du pfunc als Referenz übergibst, muss der default template Parameter 
entweder "string ()" oder "string (&)()" sein. Mit "string (*)()" gibt 
es die Fehlermeldung:
1
In member function 'void C<A, B>::process(int, ProcessFunctorType&) [with ProcessFunctorType = std::basic_string<char> (*)(), A = int, B = int]':
2
default argument for parameter of type 'std::basic_string<char> (*&)()' has type 'std::string() {aka std::basic_string<char>()}'

Also:
1
// entweder so
2
  template < typename ProcessFunctorType =  string () >
3
  void process(int i, ProcessFunctorType &pfunc = printNothing)
4

5
// oder so
6
  template < typename ProcessFunctorType =  string (&)() >
7
  void process(int i, ProcessFunctorType &pfunc = printNothing)
8

9
// oder als Funktionszeiger
10
  template < typename ProcessFunctorType =  string (*)() >
11
  void process(int i, ProcessFunctorType pfunc = printNothing)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren