struct to/from std::tuple conversion

后端 未结 4 1839
[愿得一人]
[愿得一人] 2021-02-05 13:30

Assuming I have struct and std::tuple with same type layout:

struct MyStruct { int i; bool b; double d; }
using MyTuple = std::tuple<         


        
4条回答
  •  情话喂你
    2021-02-05 14:09

    We can use structured bindings to convert a struct into a tuple with a bit of work.

    Struct-to-tuple is very awkward.

    template
    struct to_tuple_t;
    
    template<>
    struct to_tuple_t<3> {
      template
      auto operator()(S&& s)const {
        auto[e0,e1,e2]=std::forward(s);
        return std::make_tuple(e0, e1, e2);
      }
    };
    

    Now, write a to_tuple_t for each size you want to support. This gets tedious. Sadly I know of no way to introduce a parameter pack there.

    template
    auto to_tuple(S&& s) {
      return to_tuple_t{}(std::forward(s));
    }
    

    I know of no way to calculate the value of N required either. So you'd have to type the 3 in auto t = to_tuple<3>(my_struct); when you call it.

    I am not a master of structured bindings. There is probably a && or & or a decltype that would permit perfect forwarding on these lines:

        auto[e0,e1,e2]=std::forward(s);
        return std::make_tuple(e0, e1, e2);
    

    but without a compiler to play with, I'll be conservative and make redundant copies.


    Converting a tuple into a struct is easy:

    template
    S to_struct( std::index_sequence, Tup&& tup ) {
      using std::get;
      return {get(std::forward(tup))...};
    }
    template
    S to_struct( Tup&&tup ) {
      using T=std::remove_reference_t;
    
      return to_struct(
        std::make_index_sequence{}>{},
        std::forward(tup)
      );
    }
    

    SFINAE support based off tuple_size might be good for to_struct.

    The above code works with all tuple-likes, like std::pair, std::array, and anything you custom-code to support structured bindings (tuple_size and get).


    Amusingly,

    std::array arr{1,2,3};
    auto t = to_tuple<3>(arr);
    

    works and returns a tuple with 3 elements, as to_tuple is based on structured bindings, which work with tuple-likes as input.

    to_array is another possibility in this family.

提交回复
热议问题