0

I am brushing up on some C++11 and am having a bit of a hard time understanding something.

std::function lets me pass any Callable type as a function object. I know what it does and how to use it.

void foo(int a, int b) {} 
std::function<void (int, int)> bar = foo;
...

bar is a callable object who'se target is foo, a function that takes two ints as parameters.

What I don't understand is exactly what void (int, int) means...

  • I know it is the template parameter I am giving the compiler.
  • I know that from it the compiler interprets that the callable type must take two ints and return void.

But, void (int, int) doesn't appear to "name a type".

  • void (*)(int, int) is a pointer to a void returning function that takes two ints
  • void (Foo*::)(int, int) is a pointer to Foo's void returning function that takes two ints

In fact the following toy snippet compiles fine.

class Foo {};
int main(int, char**)
{
    void (*)(int, int);
    void (Foo*::)(int, int);
}

But adding the expression void (int, int) causes a compile time error.

I did a little bit more digging around before posting my question. The following code snippet compiles:

class Foo {};

template <typename T>
struct Bar
{
    typedef T type;
};

void a(int b, int c) {}

int main(int, char**)
{
    void (*)(int, int);
    void (Foo::*)(int, int);

    Bar<int (int, int)> bar;
}

But attempting to use Bar::type in any way produces another error: "invalidly declared function type".


TLDR: What exactly does the expression void (int, int) mean and why is it a valid template parameter?

Thanks for any help you can send my way.

dyp
  • 38,334
  • 13
  • 112
  • 177
JDR
  • 237
  • 4
  • 8
  • What compiler and options do you use for your "toy snippet"? As far as I can tell, it shouldn't compile.. – dyp Jun 10 '15 at 22:35
  • I'm running g++ 4.6.3 on Ubuntu 12.04LTS. Compiling with simple `g++ test.cpp -o test`, no flags or anything. – JDR Jun 10 '15 at 22:36
  • 4
    Related/duplicate: [Syntax of C++ templates with function type parameters](http://stackoverflow.com/q/7245235/) – dyp Jun 10 '15 at 22:36
  • 1
    *"no flags or anything"* That's not a good idea for many compilers. For g++, I'd suggest use `-std=c++11 -pedantic -Wall -Wextra` to specify the version of the Standard it shall follow, and warn about non-standard extensions it accepts. – dyp Jun 10 '15 at 22:38
  • 2
    Thanks a bunch for the second reply, it was exactly the answer I was looking for. I looked around for it and really didn't run into it. It's a **function signature**. Function signatures can be passed as template parameters -- I didn't know... Hey thanks again. – JDR Jun 10 '15 at 22:41
  • So you agree that `void (*)(int, int)` names a type, and that it's a pointer to something. How would you name the type of the thing it points to? – David Schwartz Jun 10 '15 at 22:58
  • 2
    @JDR Someone very pedantic might point out that `void(int,int)` is not actually a *function signature*, since the signature of (non-template) functions does not contain the return type ;) (That makes me very pedantic, I guess.) It can be called a *function type*, since it's the type of a function. You can even declare, but not define a *function* using a *function type*. E.g. `using FT = void(int); FT myFunc; void myFunc(int) {}` – dyp Jun 10 '15 at 23:01

2 Answers2

1

Not all types have values. void is the most well know example.

void(int,int) is just a type that is the type of no values. And it is useful, so it is used.

The type can be used outside of template arguments in a few spots. For example, it can be used to declare a method or a function, or a pointer to the type can be used as a function pointer, or a reference as a function reference.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
0

dyp pointed me to the correct answer. This was a duplicate question.

void (int, int) represents a "function signature" and function signatures can be passed as template parameters.

Community
  • 1
  • 1
JDR
  • 237
  • 4
  • 8
  • 1
    Specifically, `void(int,int)` is not only a signature, but in _certain_ contexts, is also a type. Namely, the type of the "object" that `void(*)(int,int)` points to. functions aren't truly objects in C++ though, for the same reason that `void(int,int)` isn't a real type: the type has no size. – Mooing Duck Jun 10 '15 at 22:56
  • 3
    @TBohne `void` also has no size, and so does `int[]`. The C++ Standard calls all of them types, though. `void(int,int)` isn't a signature either, using the terminology of the Standard. – dyp Jun 10 '15 at 23:02