我希望能够推断出一个可调用的第一个参数。我可以让它免费和成员函数工作,但我正在与lambdas挣扎。我可以使用一些技巧吗?
这是一个例子。在以下match
函数中,我想使用T
。
template<class T>
void match(void (*)(T*, int)) { /* First */ }
template<class T>
void match(void (T::*)(int)) { /* Second */ }
template<class T>
void match(std::function<void(T,int)>) { /* Third */ }
struct A
{
void f(int) {}
};
void g(A*, int) {}
match(&A::f); // Ok, matches first
match(&g); // Ok, matches second
match([](A*, int) {}); // Not Ok
match([&](A*, int) {}); // Not Ok
答案 0 :(得分:2)
你不能。
template<class T>
void g(T*, int) {}
无法正常工作
void g(void*, int) {}
void g(std::string**, int) {}
无效。
同样的问题与lambdas有关。
作为一般规则,您可以询问&#34;我可以使用Y&#34;来调用X,您无法获得签名。
std::function
不是lambda,lambda不是std::function
。它们是不相关的类型,除了您可以将lambda转换为具有任何兼容签名的std::function
这一事实,就像您可以转换任何可调用对象一样。
如果您足够限制问题空间,可以编写一个traits类来提取传入对象上operator()
的签名,并将其视为lambda的参数。
这在C ++ 11中是一个坏主意,它在C ++ 14和C ++ 17中通常会变得更糟。 [](auto a, int b){}
是C ++ 14中的lambda(许多C ++ 11编译器都支持它),并且第一个参数没有固定类型。
通常,更好的方法是将签名分开捆绑,而不是可调用。这违反了C ++ 11中的DRY(不要重复自己),但在C ++ 14中,lambda只能采用auto&&
个参数。
另一种方法是问问题&#34;这些类型中的哪些类型可以工作&#34;哪些可以完成。通常,您没有与您合作的无限类型系列,而是一个枚举集。
答案 1 :(得分:0)
我只知道一种方式:通过std::function
match(std::function<void(A*, int)>([](A*, int) {}));
match(static_cast<std::function<void(A*, int)>>([&](A*, int) {}));