我想要一些方法来获取 lambda 函数的第一个参数类型,这可能吗?
例如
代替:
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 中所做的工作:
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));
}
我尝试过简化代码,但任何尝试似乎都会破坏它。
最佳答案
最简单的选项是让 operator()
本身成为一个模板:
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:
#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是一个关于 GCC 的示例。然而,MSVC10 根本不编译代码。见 this question of mine了解更多详情。基本上,MSVC10 不会将 decltype(&F::operator())
视为依赖类型。这是在 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; });
}
关于c++ - 获取 lambda 参数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8711855/