Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prototyped function of structs

Today I came across this piece of code:

int main() {
  struct Foo {};
  struct Bar {};

  Foo(b)(int (Bar*c)); // ?

  return 0;
}

I have absolutely no idea what is going on. My compiler (VC14) warns me about unused prototyped function?

What does this line do (declare a function: which name, what parameters and return type? How to call it?)

Foo(b)(int (Bar*c));

Thank you in advance for helping me out!

like image 873
Viatorus Avatar asked Sep 12 '15 12:09

Viatorus


3 Answers

This declares a function called b that:

  • takes int (Bar*c) as its argument;
  • returns Foo.

The type of the argument, int (Bar*c), is a pointer to a function that takes a pointer to Bar and returns an int. Here, c is the name of the argument and can be omitted: int (Bar*).

Here is how you can call b:

int main() {
  struct Foo {};
  struct Bar {};

  Foo(b)(int (Bar* c)); // the prototype in question

  int func(Bar*);       // a function defined elsewhere
  Foo result = b(func);

  return 0;
}
like image 64
NPE Avatar answered Nov 08 '22 04:11

NPE


This is not valid C (because the names Foo and Bar don't refer to types; you would have to use the struct keyword or use a typedef).

In C++, this is a surprising but valid declaration. It declares b as a function returning Foo and taking an argument of type "(pointer to) function returning int taking an argument of type pointer to Bar".

In order to generate a readable type declaration, I've written the following code:

#include <typeinfo>
#include <iostream>


int main() {
    struct Foo {};
    struct Bar {};

    Foo(b)(int (Bar*c));
    std::cout << typeid(b).name();

    return 0;
}

Then I've compiled it and filtered its output through c++filt. The result was:

main::Foo (int (*)(main::Bar*))

which is entirely clear.

like image 23
The Paramagnetic Croissant Avatar answered Nov 08 '22 04:11

The Paramagnetic Croissant


Actually, my compiler (Clang 3.5) gives me the following warning:

warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]

Which is more on point, as you are dealing with with Most vexing parse.

The following declaration:

Foo(b)(int (Bar*c));

declares a b function pointer pointing to a function that returns Foo and takes as an argument a function that returns int and takes pointer to Bar an an argument (e.g.: int (Bar*c)).

Your compiler probably thinks this is a prototype of a function, thus the warning.

like image 27
syntagma Avatar answered Nov 08 '22 03:11

syntagma