获取lambda参数类型 [英] Get lambda parameter type
问题描述
我想要某种方式获得lambda函数的第一个参数类型,这是否可能?
I would like some way to get the first parameter type of a lambda function, is this possible?
例如。
而不是:
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;});
我想:
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;});
根据Xeo的答案,这是我在VS2010工作:
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 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;});
现在, ,以下代码应该正常工作。但是,它不与MSVC10感谢一个错误:
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; });
}
这里是一个关于如何看起来与GCC的例子。然而,MSVC10只是不编译代码。请参见此问题我的进一步详细。基本上,MSVC10不将 decltype(& F :: operator())
视为依赖类型。这是一个在聊天讨论中设计的解决方案:
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; });
}
这篇关于获取lambda参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!