Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template parameter 'F' is ambiguous

Tags:

c++

c++11

#include <functional>
#include <iostream>
template<typename T>
class MaybePtr{
    T* ptr;

public:
    MaybePtr(T* p) : ptr(p) {}

    template <typename F,typename R = std::result_of<F(T*)>::type>
    R Get(F access,F default){
        if (ptr != nullptr)
            return access(ptr);
        else
            return default(ptr);   
    }
};
template <typename T>
void f_void(T*) {}
int main(){
    int * iptr = new int;
    *iptr = 10;
    auto m = MaybePtr<int>(iptr);
    auto f = [](int* i) -> int {return *i + 1; };
    auto f1 = [](int* i) -> int { return 0; };
    int r = m.Get(f, f1); // error C2782
    std::cout << f(iptr);
    int i;
    std::cin >> i;
}

Error

error C2782: 'R MaybePtr<int>::Get(F,F)' : template parameter 'F' is ambiguous

Why is F ambiguous? It should know that F is a function that takes a T* and returns a R.

like image 693
Maik Klein Avatar asked Jul 28 '14 11:07

Maik Klein


1 Answers

A lambda with an empty closure may decay to a function pointer but here :

static_assert( std::is_same<decltype(f),decltype(f1)>::value,"different types" );

The error is normal, also Visual Studio is laxist, but you miss a typename and default is a reserved keyword.

template <typename F,typename R = typename std::result_of<F(T*)>::type>

A trick exists: force the lambda to decay to a function pointer. The below line compiles and does what you expect, of course, only valid with empty closure :

int r = m.Get(+f, +f1);
like image 189
galop1n Avatar answered Oct 24 '22 03:10

galop1n