I am exploring template parameter deduction in C and am currently facing the problem to deduce the parameter to a lambda and the return type of the method it's passed to as a parameter at the same time. I think it should be possible, since all the types are known at compile time, but I fail to find the solution.
Some my question is:
Is it possible to change the template struct Action in such a way that the last line containing result3 =... will compile? What changes a necessary
Compiler: gcc 7.5 and gcc 12.1
Thank you very much for your help!
template <typename Function>
struct function_traits : public function_traits<decltype(&Function::operator())> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
typedef const std::function<ReturnType(Args...)> function;
};
template <typename Function>
typename function_traits<Function>::function to_function (Function& lambda) {
return static_cast<typename function_traits<Function>::function>(lambda);
}
template<typename A>
struct Action{
A a;
Action(A const& a_) : a(a_){}
//allows action<type>(auto a){...})
template<typename B>
Action<B> action(std::function<B(A const&)> const& f) const{
return Action<B>(f(a));
}
//allows action([](A a){....})
template<typename CallableT>
auto action(CallableT const& f) -> decltype(auto){
auto g = to_function(f);
using TargetType = decltype(g(a));
return action<TargetType>(g);
}
//How to combine both????
};
void useAction(){
Action<int> a(10);
//both is possible
auto result1 = a.action([](int a){return static_cast<double>(a);});
auto result2 = a.action<double>([](auto a){return static_cast<double>(a);});
//The following does not compile. Can it be made to compile?
auto result3 = a.action([](auto a){return static_cast<double>(a);});
}
CodePudding user response:
Function::operator()
may be a template, in which case &Function::operator()
will fail.
Function::operator()
may be overloaded, in which case &Function::operator()
will also fail.
A lambda with an auto
parameter has a template operator()
.
struct function_traits
doesn't know and doesn't care about Action<A>
. All it has is your lambda.
Get rid of to_function
and associated machinery, you don't need them.
// auto g = to_function(f); <--- not needed
using TargetType = decltype(f(a));
std::function<TargetType(A const&)> g = f;