I have a simple class which stores a callable (either a lambda or global function) and a void*, both of which are passed on construction:
#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
}
The line indicated above does not compile. From https://godbolt.org/z/7K3K48Tn4, I feel the relevant error is:
could not match 'Res (*)(void *, Args...)' against '(lambda at <source>:28:13)'
LyricAnatali(Res(*)(void*, Args...), void*) -> LyricAnatali<Res(Args...)>;
I don't understand enough about deduction guides to know how to fix this. Can someone please advise how I can get this to work when passing a lambda?
CodePudding user response:
lambda is a class type with operator()
(const
in this case), and would not match a function pointer, you'd need to write deduction guide for that. (this is general template deduction rule, not limit to CTAD)
a possible implementation
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>;