C++ 我可以更改通用变量lambda的模板参数推断顺序吗?
以下面的代码为例,这是一个简化的示例:C++ 我可以更改通用变量lambda的模板参数推断顺序吗?,c++,templates,variadic-templates,c++20,generic-lambda,C++,Templates,Variadic Templates,C++20,Generic Lambda,以下面的代码为例,这是一个简化的示例: 模板 无效foo(F){ //bool some=is_variadic_v;//场景#1 bool some=true;//场景2 f(int(some),int(some)); } int main(){ 自动部分=[](int i,int j){ std::cout“编译器现在是否将sizeof…(params)同时推断为2和13”两者!但不是同时。它验证(“实例化”是正确的词)两种情况下的lambda体(即,对于尝试调用lambda的每一组参数类型
模板
无效foo(F){
//bool some=is_variadic_v;//场景#1
bool some=true;//场景2
f(int(some),int(some));
}
int main(){
自动部分=[](int i,int j){
std::cout“编译器现在是否将sizeof…(params)同时推断为2和13”两者!但不是同时。它验证(“实例化”是正确的词)两种情况下的lambda体(即,对于尝试调用lambda的每一组参数类型)。我有XY问题的感觉。为什么你需要知道lambda是否是可变的?@HolyBlackCat这听起来很奇妙,同时对我来说也很可怕。在通常的SFINAE中,只有当实例化在返回类型或(模板)中产生错误时,它才会删除重载候选项根据你的理论,如果我添加static_assert(2==sizeof…(params));在cout之前,它仍然应该编译,对吗?但它不是!有一点我不明白。@HolyBlackCat关于XY:我有一个函数,它将实例化编译时循环N次,N是传递函数的算术数。如果该函数是可变的,我假设一个最大可感循环计数,它通常不等于我认为函数是“可变的”,这是相当令人困惑的,因为你正在谈论两个不同版本的代码,似乎重要的部分不包括在这个问题中。链接可能腐烂,也链接到其他的问题/答案。如果答案被编辑了呢?请在你的问题中包含所有的代码。“编译器现在是否将sizeof…(params)同时推断为2和13”都是!但不是同时。它验证(“实例化”是正确的词)两种情况下的lambda体(即,对于您尝试调用lambda的每一组参数类型)。我有XY问题的感觉。为什么你需要知道lambda是否是可变的?@HolyBlackCat这听起来很奇妙,同时对我来说也很可怕。在通常的SFINAE中,只有当实例化在返回类型或(模板)中产生错误时,它才会删除重载候选项根据你的理论,如果我添加static_assert(2==sizeof…(params));在cout之前,它仍然应该编译,对吗?但它不是!有一点我不明白。@HolyBlackCat关于XY:我有一个函数,它将实例化编译时循环N次,N是传递函数的算术数。如果该函数是可变的,我假设一个最大可感循环计数,它通常不等于我认为函数是“可变的”,这是相当令人困惑的,因为你正在谈论两个不同版本的代码,似乎重要的部分不包括在这个问题中。链接可能腐烂,也链接到其他的问题/答案。如果答案被编辑了呢?请在你的问题中包含所有的代码。
#include <utility>
#include <type_traits>
#include <iostream>
constexpr int max_arity = 12; // if a function takes more arguments than that, it will be considered variadic
struct variadic_type { };
// it is templated, to be able to create a
// "sequence" of arbitrary_t's of given size and
// hence, to 'simulate' an arbitrary function signature.
template <auto>
struct arbitrary_type {
// this type casts implicitly to anything,
// thus, it can represent an arbitrary type.
template <typename T>
operator T&&();
template <typename T>
operator T&();
};
template <
typename F, auto ...Ints,
typename = decltype(std::declval<F>()(arbitrary_type<Ints>{ }...))
>
constexpr auto test_signature(std::index_sequence<Ints...> s) {
return std::integral_constant<int, size(s)>{ };
}
template <auto I, typename F>
constexpr auto arity_impl(int) -> decltype(test_signature<F>(std::make_index_sequence<I>{ })) {
return { };
}
template <auto I, typename F, typename = std::enable_if_t<(I > 0)>>
constexpr auto arity_impl(...) {
// try the int overload which will only work,
// if F takes I-1 arguments. Otherwise this
// overload will be selected and we'll try it
// with one element less.
return arity_impl<I - 1, F>(0);
}
template <typename F, auto MaxArity>
constexpr auto arity_impl() {
// start checking function signatures with max_arity + 1 elements
constexpr auto tmp = arity_impl<MaxArity+1, F>(0);
if constexpr (tmp == MaxArity+1)
return variadic_type{ }; // if that works, F is considered variadic
else return tmp; // if not, tmp will be the correct arity of F
}
template <typename F, auto MaxArity = max_arity>
constexpr auto arity(F&&) { return arity_impl<std::decay_t<F>, MaxArity>(); }
template <typename F, auto MaxArity = max_arity>
constexpr auto arity_v = arity_impl<std::decay_t<F>, MaxArity>();
template <typename F, auto MaxArity = max_arity>
constexpr bool is_variadic_v = std::is_same_v<std::decay_t<decltype(arity_v<F, MaxArity>)>, variadic_type>;
template <typename F>
void foo(F f) {
bool some = is_variadic_v<F>;
//bool some = true;
f(int(some), int(some));
}
int main() {
auto some = [](int i, int j) {
std::cout << i << " " << j << '\n';
};
foo([&some](auto... params) {
some(params...);
});
}
foo([&some](auto... params) {
// int foo = std::index_sequence<sizeof...(params)>{ };
std::cout << sizeof...(params) << '\n';
});
error: cannot convert 'std::index_sequence<13>' {aka 'std::integer_sequence<long unsigned int, 13>'} to 'int' in initialization
85 | int foo = std::index_sequence<sizeof...(params)>{ };