代码之家  ›  专栏  ›  技术社区  ›  Mathieu Van Nevel

将结构拆分为元组[重复]

  •  6
  • Mathieu Van Nevel  · 技术社区  · 6 年前

    问题很简单,我如何生成:

    std::tuple<float, int, double>
    

    如果我知道类型:

    struct Foo { float a; int b; double c; };
    

    如何在两种转换中检索数据?

    6 回复  |  直到 6 年前
        1
  •  9
  •   Lightness Races in Orbit Shash316    6 年前

    在C++中无法做到这一点,因为它需要一种称为 反射 .

    相反,“手动”构建元组,或者从元组开始。

    或者,您可以用Python(或类似语言)构建一个脚本来预处理代码并自动生成结果转换。

        2
  •  3
  •   Guillaume Racicot    6 年前

    可以编写转换运算符。

    struct Test {
        int a;
        float b;
        double c;
    
        explicit operator std::tuple<int, float, double>() const {
           return {a, b, c};
        }
    };
    

    然后,像这样使用它:

    int main() {
        Test t{12, 3.2f, 4.5};
        std::tuple tt = t; 
    }
    

    Live example

        3
  •  3
  •   sbabbi    6 年前

    正如另一个答案所说,在C++14中没有通用的方法来实现这一点。

    然而,C++17中有一个技巧使用结构化绑定:

    template<typename T>
    auto as_tuple_ref( T & t )
    {
       auto &[a,b,c] = t;
       return std::tie(a,b,c);
    }
    
    struct Foo { float a; int b; double c; };
    
    Foo bar;
    int & b_ref = std::get<1>( as_tuple_ref(bar) );
    

    此版本仅适用于具有3个成员的结构,但我相信,经过一些时间和努力(以及一些SFINAE),可以编写一个完全通用的解决方案(可能会涉及大量的复制粘贴)。

        4
  •  1
  •   Eljay    6 年前

    您可以手动执行。例如:

    #include <iostream>
    #include <tuple>
    
    using std::tuple;
    using std::cout;
    using std::endl;
    using std::get;
    
    struct Foo { float a; int b; double c; };
    
    int main()
    {
      auto tuple_foo = tuple<decltype(Foo::a), decltype(Foo::b), decltype(Foo::c)>{1.1f, 10, 100.001};
      cout << "<0>: " << get<0>(tuple_foo) << endl;
      cout << "<1>: " << get<1>(tuple_foo) << endl;
      cout << "<2>: " << get<2>(tuple_foo) << endl;
    }
    
        5
  •  0
  •   JFMR    6 年前

    基于这些成员名称,即:调用第一个成员 a ,第二个 b ,和第三个 c . 您可以定义以下结构模板, member_type<> ,以获取每个成员的类型:

    template<typename T>
    struct member_type : T {
        using a_t = decltype(T::a);   
        using b_t = decltype(T::b);   
        using c_t = decltype(T::c);   
    };
    

    使用此别名模板, tuple_splitter<> ,可以从 struct 与这些成员(命名为 , b c ):

    template<typename T>
    using tuple_splitter = std::tuple
                     <
                        typename member_type<T>::a_t,
                        typename member_type<T>::b_t,
                        typename member_type<T>::c_t
                     >;
    

    那么 Foo :

    tuple_splitter<Foo> foo_tuple;
    

    foo_tuple 将具有类型 std::tuple<float, int, double> .

    如果现在定义新的 结构 , Bar ,作为:

    struct Bar { int a; char b; float c; };
    

    tuple_splitter<Bar> bar_tuple;
    

    bar_tuple 将为类型 std::tuple<int, char, float> .

        6
  •  0
  •   seccpur    6 年前

    使用std::tie更容易:

    struct foo
    {
        int value1;
        int value2;
        string str;
    };
    
    void main()
    {
        std::tuple<int, int, string> a{ 1, 1, "Hello " };
        foo b;
        std::tie(b.value1, b.value2, b.str) = a;
    }