是否可以在传递给函数的通用 lambda 中显式指定模板参数?
Is it possible to explicitly specify template arguments in a generic lambda passed to a function?
我想在编译时已知大小的小容器(如 4-8 个元素)上创建一个 compile-time 循环。
只创建一个简单的循环并不难:我可以创建一个重载 operator()
的模板仿函数 F
并像下面的代码那样调用它
constexpr std::array<T, N> array{/*fill the array*/};
template <std::size_t index> struct F
{
void operator()()
{
std::vector<T> some_container{/*fill it in runtime*/};
some_container[index + some_offset] += std::get<index>(array); // Use safe array access
}
};
template <template<std::size_t> typename F, std::size_t... I>
void iterator_implementation(
const std::index_sequence<I...> /*unused*/)
{
((F<I>{}()), ...);
}
template <template<std::size_t> typename F>
void iterator()
{
iterator_implementation<F>(std::make_index_sequence<array.size()>{});
}
不过,如果我想创建十个这样的循环并想方便地传递一堆引用(闭包),我绝对应该使用 lambda 函数。
为了在 lambda 中使用 std::get
,我应该使用通用 lambda。
因此,下面示例中的仿函数可能会变成
auto f = [&some_container, some_offset]<std::size_t index>()
{
some_container[index + some_offset] += std::get<index>(array); // Use safe array access
};
我不能简单地将此 lambda 传递给 iterator
因为如果不指定模板参数就不可能传递模板类型的变量,而且我也不能简单地获取 lambda 的类型并将其作为F
以便调用 F<I>{}
重新创建 lambda。
如果我使用 typename F
而不是 template<std::size_t> typename F
,我无法调用 f<I>
,因为 typename
没有模板参数,因此不能与它们一起使用。
我还可以将 std::get<index>(array)
和 index
作为普通参数传递给 lambda 函数,避免使用模板参数但保存访问的安全性。不过,我希望尽可能使用 compile-time 常量来检查它是如何工作的。
我相信将 compile-time 常量数字作为模板参数传递可能比数字是我代码中的普通变量更有助于编译器优化我的代码(即使智能编译器应该“看到”这个并优化调用).
所以,这是一个关于新知识的问题,而不是讨论这种方法是否有帮助。
是否可以根据需要在参数包中使用通用 lambda?
P。 S.
尽管有问题标题,但它不是 的重复项,因为在我的问题中模板参数应该明确指定,而在那个问题中可以推导它。
在通用 lambda 中,operator()
是模板,但 lambda 类型不是。
不需要在索引 F<I>{}()
处实例化模板,而是需要在索引 operator()
处实例化模板。由于 lambda 具有捕获,因此需要将其作为模板参数传递,而不仅仅是类型。
替换:
template <template<std::size_t> typename F, std::size_t... I>
void iterator_implementation(
const std::index_sequence<I...> /*unused*/)
{
((F<I>{}()), ...);
}
与:
template <typename F, std::size_t... I>
void iterator_implementation(F f,
const std::index_sequence<I...> /*unused*/)
{
((f.template operator()<I>()), ...);
}
我想在编译时已知大小的小容器(如 4-8 个元素)上创建一个 compile-time 循环。
只创建一个简单的循环并不难:我可以创建一个重载 operator()
的模板仿函数 F
并像下面的代码那样调用它
constexpr std::array<T, N> array{/*fill the array*/};
template <std::size_t index> struct F
{
void operator()()
{
std::vector<T> some_container{/*fill it in runtime*/};
some_container[index + some_offset] += std::get<index>(array); // Use safe array access
}
};
template <template<std::size_t> typename F, std::size_t... I>
void iterator_implementation(
const std::index_sequence<I...> /*unused*/)
{
((F<I>{}()), ...);
}
template <template<std::size_t> typename F>
void iterator()
{
iterator_implementation<F>(std::make_index_sequence<array.size()>{});
}
不过,如果我想创建十个这样的循环并想方便地传递一堆引用(闭包),我绝对应该使用 lambda 函数。
为了在 lambda 中使用 std::get
,我应该使用通用 lambda。
因此,下面示例中的仿函数可能会变成
auto f = [&some_container, some_offset]<std::size_t index>()
{
some_container[index + some_offset] += std::get<index>(array); // Use safe array access
};
我不能简单地将此 lambda 传递给 iterator
因为如果不指定模板参数就不可能传递模板类型的变量,而且我也不能简单地获取 lambda 的类型并将其作为F
以便调用 F<I>{}
重新创建 lambda。
如果我使用 typename F
而不是 template<std::size_t> typename F
,我无法调用 f<I>
,因为 typename
没有模板参数,因此不能与它们一起使用。
我还可以将 std::get<index>(array)
和 index
作为普通参数传递给 lambda 函数,避免使用模板参数但保存访问的安全性。不过,我希望尽可能使用 compile-time 常量来检查它是如何工作的。
我相信将 compile-time 常量数字作为模板参数传递可能比数字是我代码中的普通变量更有助于编译器优化我的代码(即使智能编译器应该“看到”这个并优化调用).
所以,这是一个关于新知识的问题,而不是讨论这种方法是否有帮助。
是否可以根据需要在参数包中使用通用 lambda?
P。 S.
尽管有问题标题,但它不是
在通用 lambda 中,operator()
是模板,但 lambda 类型不是。
不需要在索引 F<I>{}()
处实例化模板,而是需要在索引 operator()
处实例化模板。由于 lambda 具有捕获,因此需要将其作为模板参数传递,而不仅仅是类型。
替换:
template <template<std::size_t> typename F, std::size_t... I>
void iterator_implementation(
const std::index_sequence<I...> /*unused*/)
{
((F<I>{}()), ...);
}
与:
template <typename F, std::size_t... I>
void iterator_implementation(F f,
const std::index_sequence<I...> /*unused*/)
{
((f.template operator()<I>()), ...);
}