将结构拆分为元组

Split a struct into a tuple

问题很直接,我怎么生成:

std::tuple<float, int, double>

如果我知道类型:

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

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

您可以手动完成。例如:

#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;
}

您不能在 C++ 中执行此操作,因为它需要一种称为 反射 的语言功能。

相反,"manually" 构建元组或首先从元组开始。

或者,您可以在 Python(或类似的)中构建一个脚本来预处理您的代码和 auto-generate 生成的转换。

基于这些成员名称,即:第一个成员称为 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 定义一个元组,其中包含这样的成员(名为 abc ):

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>.

如果您现在定义一个新的 structBar,如:

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

然后:

tuple_splitter<Bar> bar_tuple;

bar_tuple 将是 std::tuple<int, char, float>.

类型

你可以写一个转换运算符。

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

使用 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;
}

正如其他答案所说,在 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),可以编写一个完全通用的解决方案(并且它可能会涉及很多 copy-paste).