【问题标题】:How can you have multiple lines or statements inside a C++ pack expansion?如何在 C++ 包扩展中包含多行或语句?
【发布时间】:2021-01-17 15:54:35
【问题描述】:

假设我有一些像下面这样的简单代码,它只打印一个元组中的所有值并跟踪当前迭代。

#include <iostream>
#include <tuple>
#include <utility>

using std::cout;

int main() {
    std::tuple<int, double, size_t, unsigned, short, long long, long> my_tuple(7, 4, 1, 8, 5, 2, 9);
    //Can you spot the pattern? :)
    std::apply(
        [](auto&&... current_value) {
            size_t i = 0; //This is only executed once
            ((
                cout << i++ << ", " << current_value << "\n" //This is repeated the length of the tuple
            ), ...);
        }, my_tuple
    );
    return 0;
}

例如,如果我想仅在索引大于 2 时打印元组值,我该怎么做?我不能简单地将if 放在cout 之前,因为不允许使用语句(repl.it 上有[cquery] expected expression)。

更一般地说,如何在包扩展中执行多行代码或语句之类的操作?

在内部使用 lambda,例如

std::apply(
    [](auto&&... current_value) {
        size_t i = 0;
        ((
            [&current_value, &i](){
                cout << i << ", " << current_value << "\n";
                ++i;
            }()
        ), ...);
    }, my_tuple
);

但我无法想象这是最有效(或预期)的解决方案。

【问题讨论】:

  • 实际上 lambda 可能是最好的方法。一个好的 C++ 编译器可能能够内联 lambda。

标签: c++ lambda c++17 stdapply pack-expansion


【解决方案1】:

单独声明 lambda 然后折叠调用它会更好:

auto f = [&](auto& value){
    cout << i << ", " << value << "\n";
    ++i;
};
(f(current_value), ...);

您还可以使用 Boost.Mp11 的 tuple_for_each 来避免间接层:

size_t i = 0;
tuple_for_each(my_tuple, [&](auto& value){
    cout << i << ", " << value << "\n";
    ++i;
});

这是一种比通过std::apply 更直接的方法。即使您不想使用 Boost.Mp11(而且您应该想要),这也很容易实现。


有一个名为扩展语句的语言提案,这将使它成为一流的语言功能。它并没有完全实现 C++20,但可能是 C++23:

size_t i = 0;
template for (auto& value : my_tuple) {
    cout << i << ", " << value << "\n";
    ++i;
}

【讨论】:

  • 是 for... 语法的不同提案的模板还是它们不相关?
  • @NoSenseEtAl for ... 已重命名为 template for
  • 但是 co_为什么有人会这样做? :( 我真的希望这是出于解析的原因,而不是因为人们抱怨只有 3 个点不够明显......
  • @NoSenseEtAl 正如你在我上面的使用中看到的,没有包。那么为什么要选择基于包的语法呢?
  • 取决于...对您意味着什么,对我来说,它意味着具有类型列表(包、变体)的东西,而不仅仅是包。虽然我可能更喜欢 for(auto& value : my_tuple...) 语法,但这可能会使语法不愉快。
猜你喜欢
  • 1970-01-01
  • 2023-04-05
  • 2014-06-14
  • 2016-08-11
  • 2021-08-22
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 2020-09-21
相关资源
最近更新 更多