我想查询lambda /函数,了解它使用了多少参数。 小(伪)示例代码:
template <class InputIterator, class Predicate>
bool visitAll( InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr)
{
for(; f != l; ++f)
{
if(number_of_arguments(p) == 1)
{
if(!p(*f))
return false;
}
else
{
if(!p(*f, *d))
return false;
}
}
}
请注意,我要求的功能是number_of_arguments(...)
。
我一直在Closure和std :: function引用中搜索,但没有找到关于解决方案的线索。
感谢您的帮助!
答案 0 :(得分:1)
显然,您发布的代码没有多大意义,因为无论如何p(*f)
或p(*f, *d)
都无法编译。因此,您需要将其拆分为两个模板,然后您可以使用相当简单的SFINAE方法测试Predicate
的参数数量:
template <class InputIterator, class Predicate>
bool visitAll( InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr,
decltype(declval<Predicate>()(*declval<InputIterator>()),1) unused = 1)
{
cout << "1" << std::endl;
for(; f != l; ++f)
{
if(!p(*f))
return false;
}
return true;
}
template <class InputIterator, class Predicate>
bool visitAll( InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr,
decltype(declval<Predicate>()(*declval<InputIterator>(), declval<UserData>()),1) unused = 1)
{
cout << "2" << std::endl;
for(; f != l; ++f)
{
if(!p(*f, *d))
return false;
}
return true;
}
用法:
std::vector<int> a{1,2};
const auto t = [](int x){ return 1;};
const auto t2 = [](int x, UserData y){ return 1;};
UserData d;
visitAll(a.begin(), a.end(), t);
visitAll(a.begin(), a.end(), t2, &d);
当然,您可以使用std::bind
通过从第二个版本调用第一个版本来避免代码重复。
另一种方法是使用类似于std::bind
检查它所需的参数数量的代码:
template<typename _Func>
struct noa_helper {
};
template<typename _Ret, typename... _Args>
struct noa_helper<_Ret (*)(_Args...)> {
static int noa() { return sizeof...(_Args); }
};
template<class F>
int number_of_arguments(F f) {
return noa_helper<typename std::decay<F>::type>::noa();
}
void foo();
int bar(int x, int y);
...
std::cout << number_of_arguments(foo) << std::endl; // prints 0
std::cout << number_of_arguments(bar) << std::endl; // prints 2
这仅适用于真实函数,而不适用于lambdas,也不适用于std::function
,但可能更多的模板魔法可以使其适用于后两个类别。