#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 C2782: 'R MaybePtr<int>::Get(F,F)' : template parameter 'F' is ambiguous
为什么F模棱两可?应该知道F是一个取T *并返回R的函数.
解决方法
带有空闭包的lambda可能会衰减为函数指针,但在这里:
static_assert( std::is_same<decltype(f),decltype(f1)>::value,"different types" );
错误是正常的,Visual Studio也是laxist,但是你错过了一个typename,而default是一个保留的关键字.
template <typename F,typename R = typename std::result_of<F(T*)>::type>
存在一个技巧:强制lambda衰减为函数指针.下面的行编译并执行您期望的操作,当然,仅对空闭包有效:
int r = m.Get(+f,+f1);