2016-04-04 9 views
-1

Ich bin verwirrt, warum Sie eine Funktion wieWarum sind unbenannte Parameter nützlich?

definieren
int func_useless(int) { return 2; } 

, dass ein ungenannter int als Eingabe verwendet, tut aber nichts mit ihm, im Gegensatz zu

int func_useful(int a) { return a; } 

Zum Beispiel könnten Sie nennen

int x = func_useless(3); // x is 2 

wo passing ein int zu func_useless wurde benötigt, aber ergibt nichts.

Wann wäre die Weitergabe von etwas, das nicht verwendet werden kann, immer nützlich? Warum ist das ein Merkmal der Sprache?

+0

Also, "warum sind unbenannte Parameter nützlich"? –

+1

Siehe auch: http://stackoverflow.com/questions/12186698/on-unnamed-parameters-to-functions-c –

+0

Diese Frage ist ein Duplikat, aber im Gegensatz zu „On unbenannte Parametern“, die Frage ist eigentlich eine bestimmte Frage zu die Nützlichkeit unbenannter Parameter, die hilfreich für Leute ist, die herausfinden wollen, warum dies nützlich ist. – OrangeSherbet

Antwort

0

Ich kann keinen Grund denken, der auch nützlich wäre.

Was ich erwarte, Sie werden immer auf die drängendsten Parse:

int main() 
{ 
    int funk1(); 
    int funk2(int()); 

    funk2(funk1); 
} 

Dies ist eine Erklärung, und Sie brauchen nicht die hier Namen. Sie werden wahrscheinlich am Definitionspunkt benannt.

Edit:

Eigentlich habe ich denke an eine Verwendung:

int whatnot() { return 6; } 

void somefun(int (*callback)(int())) 
{ 
    callback(whatnot); 
} 

int my_callback(int()) { return 42; } 

int main() 
{ 
    somefun(my_callback); 
} 

my_callback nicht benötigen oder die Funktionsparameter verwenden, aber es muss es akzeptieren, um die Callback-Schnittstelle zu gehorchen als angegeben von somefun.

+0

Most vexing parse: Das war genau das, was all diese Verwirrung verursacht hat, speziell im Zusammenhang mit threading, wo Sie eine Funktion an einen Thread übergeben müssen, aber es wird als Deklaration interpretiert, wie 'std :: thread (constructor()) 'vs' std :: thread ((constructor())) ' – OrangeSherbet

+0

Es gibt Tonnen von Gebrauch für thist. Tag Versand und Sfinae (in einer seiner Inkarnationen), um ein paar zu nennen. – SergeyA

1

Hier ist ein Anwendungsfall. Sie haben eine Funktion, die eine Funktion übernimmt, und tut etwas mit ihm:

int sumFrom0To9(int *func(int)) { 
    int acc = 0; 
    for (int i = 0; i < 10; i++) { acc += func(i); } 
    return acc; 
} 

Sie in jedem einzelnen argument Funktion übergeben können Sie, auch wollen, sagen wir, etwas wie folgt aus:

int identity(int) { return 1; } 
+1

Ich werde diese Funktion 'identity' nicht nennen ...' one' scheint besser. – Jarod42

0

Unbenannt Parameter können manchmal nützlich sein, wenn Sie die binäre Schnittstelle einer Funktion beibehalten (ihre Signatur nicht ändern) möchten, aber keine Verwendung mehr für das Argument haben und Compiler-Warnungen über nicht verwendete Argumente schließen möchten.

2
  • Rückrufschnittstellen; Eine andere Bibliothek erfordert möglicherweise einen Rückruf mit einer bestimmten Signatur, aber Ihr Rückruf interessiert sich nicht für den Wert eines bestimmten Arguments.
  • Wenn Sie nur den Typ des Arguments interessiert, aber nicht seinen Wert.

    • vielleicht weil alle Werte dieses Typs sind äquivalent, z.B. std::nullptr_t, oder Tag-Typen wie std::allocator_arg_t oder std::nothrow_t oder std::piecewise_construct_t oder std::input_iterator_tag.
    • vielleicht weil das Argument nur Überladungsauflösung verwendet wird, um zu steuern, zum Beispiel:

      template<class T> 
      auto do_foo(const T& t, int) -> decltype(t.foo()) { return t.foo(); } 
      template<class T> 
      void do_foo(const T& t, long) { /* default implementation */ } 
      
      // call t.foo() if valid, otherwise provide a default implementation 
      template<class T> 
      decltype(auto) foo(const T& t) { return do_foo(t, 0); } 
      

      Der Wert des zweiten Parameters von do_foo keine Rolle spielt; Es wird nur verwendet, um die Überladungsauflösung für den do_foo(t, 0) Anruf zu steuern, wenn beide do_foo s lebensfähig sind, indem Sie das erste besser machen.

      In der gleichen Ader haben wir operator++() (Präfix) und operator++(int) (Postfix) und ihre -- Pendants; Implementierungen des Postfix ++/-- Operatoren selten, wenn überhaupt jemals den Wert des Parameters int kümmern; Es existiert, um Präfix und Postfix zu disambiguieren.

+0

Einige Implementierungen von SFINAE. – SergeyA

1

einmaliger Gebrauch ist tag-Dispatching, das ist eine nützliche Technik in Template-Programmierung:

#include <iostream> 

struct ping_type {}; 
struct pong_type {}; 

static constexpr ping = ping_type {}; 
static constexpr pong = pong_type {}; 

void action(ping_type) { 
    std::cout << "ping" << std::endl; 
} 

void action(pong_type) { 
    std::cout << "pong" << std::endl; 
} 

int main() 
{ 
    action(ping);  
    action(pong); 
} 
Verwandte Themen