使用默认参数从 lambda 调用最少数量的参数
Call with minimal number of argument from lambda with default arguments
出于我目前正在编写的库的目的,我的目标是,给定用户指定的lambda函数,使用我选择的参数在内部调用它。
到目前为止,它工作正常,看起来像这样:
#include <tuple>
template<typename T> struct GetFinfos;
template<typename R, typename F, typename ...Args>
struct GetFinfos<R(F::*)(Args...) const> {
static std::tuple<Args...> createChosenTuple() {
return std::make_tuple(Args(1)...);
}
};
template<typename F>
void internal_lambda_call(const F & f) {
//let's suppose for convenience that we have a working call_from_tuple in C++14
std::apply(f, GetFinfos<decltype(&F::operator())>::createChosenTuple() );
}
int main()
{
auto f = [](int i, int j, int k) { };
internal_lambda_call(f); // calls f(1,1,1);
}
现在,C++14
引入了带有默认参数的 lambda 函数,我想知道库是否可以使用来自用户的这些额外信息。
auto g = [](int i, int j = 5, int k = 5) { };
据我了解,具有默认参数的 lambda 仍然只有一个ClosureType::operator ret(*)(params)()
运算符。因此,GetFinfos
对默认参数视而不见,internal_lambda_call(g)
调用g(1,1,1)
。
但是,由于我们可以访问完整的参数类型列表,因此理论上我们可以尝试使用递减的参数来调用 lambda 并选择最后一个有效的参数。
g(1,1,1) //valid call
g(1,1) //valid call
g(1); //valid call <---- last valid one
g(); //invalid call
所以我的问题是:如果有任何现有的机器,那么internal_lambda_call(g)
自动调用g(1)
或g(1,5,5)
?我在这里看到通用 lambda 可用于包装 lambda 并使其与显式数量的参数一起工作。但是我没有看到自动获得这种最小数量的参数的方法。
我没有看到自动获取此最小参数的方法。
或。。。带有一点递归和SFINAE...
#include <tuple>
#include <utility>
template <typename F, typename T, std::size_t ... Is>
constexpr auto gmna_helper (std::index_sequence<Is...> is, int)
-> decltype( (void)std::declval<F>()
(std::declval<std::tuple_element_t<Is, T>>()...),
std::size_t{} )
{ return sizeof...(Is); }
template <typename F, typename T, std::size_t ... Is>
constexpr auto gmna_helper (std::index_sequence<Is...>, long)
{ return gmna_helper<F, T>(std::make_index_sequence<sizeof...(Is)+1u>{}, 0); }
template <typename F, typename ... Ts>
constexpr std::size_t getMinNumArgs ()
{ return gmna_helper<F, std::tuple<Ts...>>(std::index_sequence<>{}, 0); }
int main ()
{
auto g = [](int, int = 5, int = 5) { };
constexpr auto n = getMinNumArgs<decltype(g), int, int, int>();
static_assert( n == 1, "!" );
}
正如同一个 OP 在评论中所说,两个gmna_helper()
(int
与long
参数)之间的签名差异是引入排序:该函数使用int
调用,因此选择接收int
的版本(如果可用)。也就是说:当类型为F
的函数仅在前sizeof...(Is)
个参数的情况下可调用时选择。
否则,当int
版本不可用(SFINAE 因decltype()
内呼叫失败而禁用)时,将选择long
(永远可用)。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何将lambda作为模板类的成员函数参数
- 使用自动推导的 lambda 参数作为常量表达式
- 如果模板没有可变参数,则 Lambda 被推导出为 std::function
- 将有状态的 lambda 传递到 C 样式函数中,而无需上下文参数
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- 将__device__ lambda 作为参数传递给 __global__ 函数
- 将 lambda 函数作为参数传递C++
- 如何将 lambda 函数作为参数发送到另一个函数
- Lambda可以用作非类型模板参数吗
- 将参数传递给泛型 lambda 时复制构造函数不正确
- 如何确定捕获不可复制参数的 lambda 的类型?
- 省略C++可变参数 lambda 中的"auto"关键字?
- 如何访问可变参数 lambda 函数参数
- 可变参数 lambda 捕获的解决方法
- 传递给多个参数 lambda 表达式的参数
- 如何编写丢弃其参数的通用可变参数 lambda
- 使用c++参数lambda函数
- 将函数模板"pass"为泛型可变参数 lambda 返回语句是好方法吗?
- c++模板非类型参数lambda函数