-1

I am confused why you can define a function like

int func_useless(int) { return 2; }

that takes as input an unnamed int, but does nothing with it, unlike

int func_useful(int a) { return a; }

For instance, you could call

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

where passing an int to func_useless was required but results in nothing.

When would passing something that cannot be used ever be useful? Why is this a feature of the language?

JoseOrtiz3
  • 1,785
  • 17
  • 28
  • So, "why are unnamed parameters useful"? – T.C. Apr 04 '16 at 21:06
  • 1
    See also: http://stackoverflow.com/questions/12186698/on-unnamed-parameters-to-functions-c – Frank Puffer Apr 04 '16 at 21:13
  • This question is a duplicate, but unlike "On unnamed parameters", the question is actually a specific question about the usefulness of unnamed parameters, which is helpful for people trying to figure out why this is useful. – JoseOrtiz3 Apr 04 '16 at 21:44

5 Answers5

2
  • Callback interfaces; another library may require a callback with a particular signature, but your callback doesn't care about the value of a particular argument.
  • When you only care about the type of the argument but not its value.

    • perhaps because all values of that type are equivalent, e.g., std::nullptr_t, or tag types like std::allocator_arg_t or std::nothrow_t or std::piecewise_construct_t or std::input_iterator_tag.
    • perhaps because the argument is only used to control overload resolution, for example:

      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); }
      

      The value of the second parameter of do_foo doesn't matter; it's only used to control overload resolution for the do_foo(t, 0) call when both do_foos are viable, by making the first one better.

      In the same vein we have operator++() (prefix) and operator++(int) (postfix) and their -- counterparts; implementations of the postfix ++/-- operators rarely if ever care about the value of the int parameter; it exists to disambiguate prefix and postfix.

T.C.
  • 133,968
  • 17
  • 288
  • 421
2

one use is tag-dispatching, which is a useful technique in template programming:

#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);
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
1

Here's a use-case. You have a function that takes a function, and does something with it:

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

You can pass in any single-arg function you want, including, say, something like this:

int identity(int) { return 1; }
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1

Unnamed parameters can sometimes be useful if you want to preserve the binary interface of a function (not change its signature) but no longer have any use for the argument and want to shut up compiler warnings about unused arguments.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
0

I can't think of any reason that would be useful either.

What I anticipate you are getting at is the most vexing parse:

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

    funk2(funk1);
}

This is a declaration, and you don't need the names here. They are likely named at point of definition.

Edit:

Actually I did think of a use:

int whatnot() { return 6; }

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

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

int main()
{
    somefun(my_callback);
}

my_callback doesn't need or use the function parameter but it needs to accept it in order to obey the callback interface as specified by somefun.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • Most vexing parse: That was exactly what caused all this confusion, specifically in the context of threading, where you must pass a function to a thread but it gets interpreted as a declaration, like `std::thread t(constructor())` vs `std::thread t((constructor()))` – JoseOrtiz3 Apr 04 '16 at 21:23
  • There are tons of usage for thist. tag dispatch and sfinae (in one of it's incarnations) to name a few. – SergeyA Apr 04 '16 at 21:23