I would like some way to get the first parameter type of a lambda function, is this possible?
e.g.
instead of:
template<typename T>
struct base
{
virtual bool operator()(T) = 0;
}
template<typename F, typename T>
struct filter : public base<T>
{
virtual bool operator()(T) override {return /*...*/ }
};
template<typename T, typename F>
filter<T> make_filter(F func)
{
return filter<F, T>(std::move(func));
}
auto f = make_filter<int>([](int n){return n % 2 == 0;});
I would like:
template<typename F>
struct filter : public base<typename param1<F>::type>
{
bool operator()(typename param1<F>::type){return /*...*/ }
};
template<typename F>
filter<F> make_filter(F func)
{
return filter<F>(std::move(func));
}
auto f = make_filter([](int n){return n % 2 == 0;});
Based on Xeo's answer this is what I got working in VS2010:
template<typename FPtr>
struct arg1_traits_impl;
template<typename R, typename C, typename A1>
struct arg1_traits_impl<R (C::*)(A1)>{typedef A1 arg1_type;};
template<typename R, typename C, typename A1>
struct arg1_traits_impl<R (C::*)(A1) const>{typedef A1 arg1_type;};
template<typename T>
typename arg1_traits_impl<T>::arg1_type arg1_type_helper(T);
template<typename F>
struct filter : public base<typename std::decay<decltype(detail::arg1_type_helper(&F::operator()))>::type>
{
bool operator()(typename std::decay<decltype(detail::arg1_type_helper(&F::operator()))>::type){return /*...*/ }
};
template<typename T, typename F>
filter<F> make_filter(F func)
{
return filter<F>(std::move(func));
}
I've tried simplifying the the code, but any attempt seems to break it.
The type of a lambda expression is unspecified. But they are generally mere syntactic sugar for functors. A lambda is translated directly into a functor.
A lambda expression is a function or subroutine without a name that can be used wherever a delegate is valid. Lambda expressions can be functions or subroutines and can be single-line or multi-line. You can pass values from the current scope to a lambda expression. The RemoveHandler statement is an exception.
In C++11 and later, a lambda expression—often called a lambda—is a convenient way of defining an anonymous function object (a closure) right at the location where it's invoked or passed as an argument to a function.
A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
The easiest option would be to just make the operator()
a template itself:
template<typename F>
struct filter
{
template<class Arg>
void operator(Arg&& arg){
// use std::forward<Arg>(arg) to call the stored function
}
};
template<typename F>
filter<F> make_filter(F func)
{
return filter<F>(std::move(func));
}
auto f = make_filter([](int n){return n % 2 == 0;});
Now, theoretically, the following code should just work. However, it doesn't with MSVC10 thanks to a bug:
#include <iostream>
#include <typeinfo>
template<class FPtr>
struct function_traits;
template<class T, class C>
struct function_traits<T (C::*)>
{
typedef T type;
};
template<class F>
void bar(F f){
typedef typename function_traits<
decltype(&F::operator())>::type signature;
std::cout << typeid(signature).name();
}
int main(){
bar([](int n){ return n % 2 == 0; });
}
Here's an example on how it would look with GCC. MSVC10, however, simply doesn't compile the code. See this question of mine for further detail. Basically, MSVC10 doesn't treat decltype(&F::operator())
as a dependent type. Here's a work-around that was devised in a chat discussion:
#include <iostream>
#include <typeinfo>
#include <type_traits>
template<class FPtr>
struct function_traits;
template<class R, class C, class A1>
struct function_traits<R (C::*)(A1)>
{ // non-const specialization
typedef A1 arg_type;
typedef R result_type;
typedef R type(A1);
};
template<class R, class C, class A1>
struct function_traits<R (C::*)(A1) const>
{ // const specialization
typedef A1 arg_type;
typedef R result_type;
typedef R type(A1);
};
template<class T>
typename function_traits<T>::type* bar_helper(T);
template<class F>
void bar(F f){
typedef decltype(bar_helper(&F::operator())) fptr;
typedef typename std::remove_pointer<fptr>::type signature;
std::cout << typeid(signature).name();
}
int main(){
bar([](int n){ return n % 2 == 0; });
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With