模板推导指南在lambda函数而不是全局函数中失败



我有一个简单的类,它存储一个可调用的(lambda或全局函数)和一个void*,它们都是在构造时传递的:

#include <iostream>
#include <vector>
#include <functional>
using namespace std;
template <typename>
class LyricAnatali;
template <typename Res, typename... Args>
class LyricAnatali<Res(Args...)> {
public:
template <typename F>
LyricAnatali(F&& f, void* data)
: m_ptr(f), m_userData(data) {}
private:
Res(*m_ptr)(void*, Args...) = nullptr;
void* m_userData;
};
// Deduction guide
template <typename Res, typename... Args>
LyricAnatali(Res(*)(void*, Args...), void*) -> LyricAnatali<Res(Args...)>;
int GlobalFunction(void*, const string& s, const vector<int>& t, int u) { return 0; }
int main() {
auto lg = [](void*, const string& s, const vector<int>& t, int u) -> int { return 0; };
LyricAnatali<int(const string& s, const vector<int>& t, int u)> func(lg, 0);  // Compiles
auto lambda = LyricAnatali(lg, 0); // Does not compile
auto global = LyricAnatali(GlobalFunction, 0); // Compiles
auto stdFunc = std::function(lg); // Compiles
}

上面指示的行不能编译。从https://godbolt.org/z/7K3K48Tn4,我觉得相关的错误是:

could not match 'Res (*)(void *, Args...)' against '(lambda at <source>:28:13)'
LyricAnatali(Res(*)(void*, Args...), void*) -> LyricAnatali<Res(Args...)>;

我对演绎指南了解不够,不知道如何解决这个问题。有人能告诉我如何才能得到这个工作时,传递一个lambda?

lambda是具有operator()(在本例中为const)的类类型,并且不匹配函数指针,您需要为此编写演绎指南。(这是一般的模板推导规则,不限于CTAD)


一个可能的实现

template <typename...>
struct parse_member{};
template <typename R, typename G, typename... A>
struct parse_member<R(G::*)(void*, A...)const>{ // and all combination of const, noexcept, volatile, &, &&, for general case 
using type = R(A...);
};
template <
typename F, 
typename sig = typename parse_member<decltype(&F::operator())>::type
>
LyricAnatali(F, void*) -> LyricAnatali<sig>;

https://godbolt.org/z/sTsovGEvd

最新更新