4

I am trying to write some functionality where I need to save different functions and later extract their arguments' types. So I'm using the function signature as template parameter. But I get somewhat unexpected results. Here's the code:

#include <functional>
#include <iostream>

template <class T>
struct foo
{
    foo()
    {
        std::cout << "class T" << std::endl;
    }
};

template <class Ret, class Arg>
struct foo<Ret(Arg)>
{
    foo()
    {
        std::cout << "Ret(Arg)" << std::endl;
    }
};

template <class T>
void save(std::function<T>)
{
    new foo<T>();
}

int main(int argc, char* argv[])
{
    std::function<void(void)> someFoo;
    save(someFoo);
    return 0;
}

So if the variable someFoo is a function with type void(void), it instantiates the first template, foo<T>. But if I change it to void(int), than I get the desired specialized template instantiated. Why is that?

Barry
  • 286,269
  • 29
  • 621
  • 977
Pavel
  • 73
  • 5

2 Answers2

5

In C++, having a void argument is actually the same as having no argument at all (unlike in C, by the way). So it would match a specialization for Ret(), but it can't match a specialization for Ret(Arg).

Arkanosis
  • 2,229
  • 1
  • 12
  • 18
3

void(void) is the exact same as void() - the second void is optional and makes no difference.

That's why the first template with no parameters is used.

maja
  • 17,250
  • 17
  • 82
  • 125