考虑我有以下内容:
void bar(int a, int b)
{
}
template<typename F, typename... Args>
void foo(F function, Args... args>
{
function(args...);
}
我想有某种方式只将必要数量的参数传递给函数,这样我就可以执行以下操作,这将导致调用bar,1,2作为参数丢弃3.不知道函数类型F需要传递多少个参数。
foo(bar, 1, 2, 3);
foo([](int a, int b){}, 1, 2, 3);
当我尝试使用以下功能特性时:
namespace detail
{
template<typename F, std::size_t... Is, class Tup>
void call_discard_impl(F&& func, std::index_sequence<Is...>, Tup&& tup)
{
std::forward<F>(func)(std::get<Is>(tup)...);
}
}
template<typename F, typename... Args>
void call_discard(F&& func, Args&&... args)
{
detail::call_discard_impl(std::forward<F>(func),
std::make_index_sequence<function_traits<F>::num_args>{},
std::forward_as_tuple(args...));
}
我明白了:
error C2510: 'F': left of '::' must be a class/struct/union
error C2065: '()': undeclared identifier
error C2955: 'function_traits': use of class template requires template argument list
在:
template <typename F>
struct function_traits : public function_traits<decltype(&F::operator())>
{}
我确实得到了成员函数版本,它不需要函数特性:
namespace detail
{
template<typename O, typename R, typename... FunArgs, std::size_t... Is, class Tup>
void call_discard_impl(O* obj, R(O::*mem_func)(FunArgs...), std::index_sequence<Is...>, Tup&& tup)
{
((*obj).*mem_func)(std::get<Is>(tup)...);
}
}
template<typename O, typename R, typename... FunArgs, typename... Args>
void call_discard(O* obj, R(O::*mem_func)(FunArgs...), Args&&... args)
{
detail::call_discard_impl(obj, mem_func,
std::make_index_sequence<sizeof...(FunArgs)>{},
std::forward_as_tuple(args...));
}
答案 0 :(得分:3)
首先,使用以下代码,您可以找到lambda或函数引用的arity:
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
using result_type = ReturnType;
using arg_tuple = std::tuple<Args...>;
static constexpr auto arity = sizeof...(Args);
};
template <typename R, typename ... Args>
struct function_traits<R(&)(Args...)>
{
using result_type = R;
using arg_tuple = std::tuple<Args...>;
static constexpr auto arity = sizeof...(Args);
};
接下来,使用元组包转发可变参数,并且只扩展到函数的arity:
template<typename F, std::size_t... Is, class T>
void foo_impl(F && f, std::index_sequence<Is...>, T && tuple) {
std::forward<F>(f)(std::get<Is>(tuple)...);
}
template<typename F, typename... Args>
void foo(F && f, Args&&... args) {
foo_impl(std::forward<F>(f),
std::make_index_sequence<function_traits<F>::arity>{},
std::forward_as_tuple(args...) );
}
答案 1 :(得分:2)
首先,我们需要一个函数来检索函数所需的数字或参数。这是使用function_traits
:
template <class F>
constexpr std::size_t nb_args() {
return utils::function_traits<F>::arity;
}
在std::index_sequence
的帮助下,我们只发送nb_args<F>()
个第一个参数:
template<typename F, std::size_t... Is, class Tup>
void foo_impl(F && f, std::index_sequence<Is...>, Tup && tup) {
std::forward<F>(f)( std::get<Is>(tup)... );
}
template<typename F, typename... Args>
void foo(F && f, Args&&... args) {
foo_impl(std::forward<F>(f),
std::make_index_sequence<nb_args<F>()>{},
std::forward_as_tuple(args...) );
}
<强> Demo 强>
答案 2 :(得分:1)
琐碎且难以扩展的解决方案是创建一个包装器,它将使用所有参数调用,但仅使用其中的前几个。
template<typename F, typename... Args>
void foo(F function, Args... args)
{
// with proper forwarding if needed
auto lambda = [](auto fnc, auto first, auto second, auto...)
{
fnc(first, second);
};
lambda(function, args...);
}
答案 3 :(得分:0)
这是一个可以与std::invoke
接受的任何内容一起使用的解决方案,该解决方案使用 feast 可能的参数调用重载。
from pathlib2 import Path
path = Path("/test/test/")
for x in path.iterdir():
print (x)