Question: I have a very strange problem. To keep things simple, lets say I want to have a function which takes 2 functions with the same declaration as arguments

```
template<typename Func>
void foo(Func a, Func b)
{
    std::cout << "good";
}

```

To try things out I took `putchar` from cstdio, and created an identical function to match the `putchar`.

```
int myPutcharFunc(int)
{
    return 0;
}

int main()
{
    auto myPutcharLambda = [](int) -> int
    {
        return 0;
    };

    foo(putchar, myPutcharFunc); // okay
    foo(putchar, myPutcharLambda);  //deduced conflicting types for parameter 'Func' ('int (__attribute__((__cdecl__)) *)(int)' and 'main()::<lambda(int)>')
}

```

Now, the lambda does not want to compile (the key is I want to use lambda capture).

So lets add template specialization, because the programmer is wiser than the machine, right? :)

```
template<typename Func>
void foo(Func a, Func b)
{
    std::cout << "good";
}

template<>
void foo(int(*)(int), int(*)(int))
{
    std::cout << "good";
}

```

No luck, the same error - why?
But for some reason, when I comment out the template specialization:

```
//template<>
void foo(int(*)(int), int(*)(int))
{
    std::cout << "good";
}

```

The code compiles. I obviously do not want to overload `foo` for EVERY set of function's arguments - thats what templates are for. Every step was tested both with msvc++ and g++. What am I doing wrong?

Answer: 
Two possibilities.

***1***: Just put `+` in front of the lambda:

```
foo(putchar, +myPutcharLambda);

```

That works because unary `+` expects an integer-like value, such as a pointer. Therefore, the lambda converts to a function pointer.

Ultimately a (non-capturing) lambda doesn't have the same type as a function pointer, even though it's willing to convert to a function pointer.

How is a compiler supposed to know which conversions are allowed to make two objects of the same type?

***2***: There is another option, making use of the fact that the `?:` is willing to do some conversions, [converting one type to another in some circumstances](https://stackoverflow.com/questions/29381171/ternary-operator-of-different-types).

```
template<typename Func1, typename Func2>
void foo2(Func1 a, Func2 b)
{
    using common_type = decltype(true?a:b); // or 'false', it doesn't matter
    foo<common_type>(a,b);
}

```
A lambda has its own type which can decay to a function pointer but not in the case of a template function match, it will for the real function as you found because of the implicit conversion. 

In the case of matching to a template you need to disambiguate and explicitly instantiate foo with the type you want or convert the lambda to a function pointer.

```
foo<decltype(putchar)>(putchar, myPutcharLambda);

```

or

```
foo(putchar, +myPutcharLambda);

```