使用c++20概念查找参数包的第n个元素

问题描述 投票:0回答:1

我正在寻找一种非递归的现代方法(至少可以使用 gcc 和 clang 进行编译)来查找可变参数包的 𝑛th 元素。事实上,似乎存在这样一个使用 c++20 概念的解决方案:Kris Jusiak 在 CppCon、CppNow 和 Meeting Cpp 上发表了演讲nth pack element,所有这些都在 2022 年进行,并且都可以在 YouTube 上找到; Alex Dathskovsky 写了一篇 LinkedIN 文章 Nth element variadic pack extract (https://www.linkedin.com/pulse/nth-element-variadic-pack-extraction-alex-dathskovsky-);当然还有其他地方可以找到这种情况。这两种解决方案非常相似,据称都表现得很好;我将在下面包括前者。遗憾的是,上述示例都无法编译。这是 Jusiak 演讲中给出的编译器资源管理器链接 (https://godbolt.org/z/WPhe5MerW),下面是副本: #include <cstddef> // adding #include <concepts> changes nothing #include <utility> template <typename, std::size_t> concept prefix = true; template <auto N> constexpr auto nth_element(auto... args) { return [&]<auto... Is>(std::index_sequence<Is...>) { return [] (prefix<Is> auto..., auto arg, auto...) { return arg; }(args...); }(std::make_index_sequence<N>()); } static_assert(1 == nth_element<0>(1)); static_assert(1 == nth_element<0>(1, 2)); static_assert(2 == nth_element<1>(1, 2)); // this line throws an error static_assert(1 == nth_element<0>(1, 2, 3)); static_assert(2 == nth_element<1>(1, 2, 3)); // and this one static_assert(3 == nth_element<2>(1, 2, 3)); // and this one

这不能在本地编译,也不能在 godbolt 上编译。评论是我自己的。以下是
gcc

的抱怨归结为:

<source>:10:27: error: mismatched argument pack lengths while expanding 'prefix<auto:2, Is>'
   9 |     return [] (prefix<Is> auto..., auto arg, auto...) {

clang

s:

<source>:9:31: note: because substituted constraint expression is ill-formed: pack expansion
contains parameter packs 'auto:1' and 'Is' that have different lengths (0 vs. 1)
    9 |     return [] (prefix<Is> auto..., auto arg, auto...) {

这似乎会导致“约束不满足”,因此模板参数推导/替换失败,导致第 9 行中的嵌套 lambda 没有匹配(函数)调用。

我尝试四处寻找,但无济于事。不确定是因为

免责声明

我不是专业人士,还是真的有点棘手!我不知道该怎么办。我尝试过一些愚蠢的事情,比如到处添加和删除省略号,比如前缀概念中的 std::size_t...,或者我们有问题的 lambda 中的

prefix<Is...>
,但都没有帮助。 LinkedIN 的帖子和会议演讲也试图对其进行分解,我希望能够充分消化这些内容,以便能够找到解决方案 - 但事实并非如此。我真诚地为没有提供更好的尝试而道歉。是的,存在其他可行的解决方案,并且可以在上述来源中找到一些解决方案,但我特别有兴趣获得其中一个使用概念进行编译的解决方案。
我还发现了一些可能有用且相关的 SO 帖子,但我无法弄清楚如何使用它们来提供帮助。许多提供递归作为解决方案。

扩展 std::index_sequence 和可变参数包时参数包长度不匹配(请参阅 questions/74805917/mismatched-argument-pack-lengths-while-expanding-stdindex-sequence-and-variadi)
  • 如何迭代参数包(参见 questions/71985500/how-to-iterate-over-a-parameter-pack)
  • 如何迭代打包的可变参数模板参数列表?问题/7230621/如何迭代打包变量模板参数列表
  • 模板参数包访问第 N 个类型和第 N 个元素(参见 questions/20162903/template-parameter-packs-access-nth-type-and-nth-element)
  • C++:迭代元组时忽略候选模板(请参阅 questions/68299663/c-candidate-template-ignored-when-iteating-over-tuple)
  • 任何有关这方面的指导或帮助将不胜感激!

现在,也许这篇文章已经太长了,下面的内容可能更适合作为(单独的)后续问题,但在 Andrei Alexandrescu 的 CppCon 2021 演讲中
安全地拥抱(并销毁)变体类型

(位于YouTube)他建议将以下内容添加到标准中以帮助处理参数包: template<typename... Ts> struct type_sequence {}; // template<typename... Ts> struct head; template<typename T, typename... Ts> struct head<type_sequence<T, Ts...>> { using type = T; }; template<typename T> using head_t = typename head<T>::type; // template<typename... Ts> struct tail; template<typename T, typename... Ts> struct tail<type_sequence<T, Ts...>> { using type = type_sequence<Ts...>; }; template<typename T> using tail_t = typename tail<T>::type; // template<typename T, typename List> struct cons; template<typename T, typename... Ts> struct cons<T, type_sequence<Ts...>> { using type = type_sequence<T, Ts...>; }; template<typename T, typename List> using cons_t = typename cons<T, List>::type;

我想知道在寻找包中第 𝑛
th

元素的概念扩展解决方案中,我们是否能够找到一种方法来用这个 std::index_sequence 替换

type_sequence
。预先感谢您!
    

c++ variadic-functions template-meta-programming c++-concepts parameter-pack
1个回答
0
投票

#include <array> #include <tuple> template <std::size_t N, typename... args_t> constexpr auto nth_element(args_t... args) { return std::get<N>(std::forward_as_tuple(args...)); } int main() { static_assert(1 == nth_element<0>(1)); static_assert(1 == nth_element<0>(1, 2)); static_assert(2 == nth_element<1>(1, 2)); // this line throws an error static_assert(1 == nth_element<0>(1, "Hello", 3.0)); static_assert(2 == nth_element<1>(1, 2, 3)); // and this one static_assert(3 == nth_element<2>(1, 2, 3)); // and this one }

© www.soinside.com 2019 - 2024. All rights reserved.