简体   繁体   中英

Iterating over a tuple by index in c++17 on MSVC?

I need to be able to iterate through a tuple at compile time, while having access to the index of recursion, in a cross-platform code. Ideally I could do it like so:

#include<tuple>
#include <array>
    
struct A { int val() { return 1; } };
struct B { 
  int v;
  B( int v): v(v) {};
  int val() { return  v * 2; } 
};

int main() {
    auto arr = std::array<int,3>{};
    auto t   = std::tuple<A,A,B> {A{}, A{}, B{7}};
    
    // set each elem in arr with the result of the corresponding elem in
    // t's val() call
    [&]<size_t ... d>(std::index_sequence<d...>) {
      ((arr[d] = std::get<d>(t).val()),...);
    }(std::make_index_sequence<3>());
}

However, this doesn't compile on MSVC with std=c++17, but does on GCC and clang. Godbolt link .

I have also considered std::apply , but AFAIK I can't have access to the index (unless I fold my tuple with an index_sequence somehow?). If I can't do it nicely with fold expressions, my next option seems to be compile time recursion, but this seems very unweildy, especially if I can't use lambda function templates because c++17.

Before I go down this route and make my code very ugly, is there a nice, idiomatic way to do what I want to do that I'm missing?

If it matter, in the full code, the size of the array and tuple, are template parameters, as are the tuple types (they all derive from a base class though).

In C++17, you can use nested apply to perform pairwise operations on two tuple elements.

auto arr = std::array<int,3>{};
auto t   = std::tuple<A,A,B> {A{}, A{}, B{7}};

std::apply([&](auto&... y) { 
    std::apply([&](auto&... x) { ((x = y.val()), ...); }, arr);
  }, t);

Demo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM