将结构拆分为元组

时间:2018-02-24 15:06:47

标签: c++ tuples metaprogramming

问题很简单,我怎么能产生:

std::tuple<float, int, double>

如果我知道类型:

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

我怎样才能在转换中检索数据?

6 个答案:

答案 0 :(得分:9)

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

相反,&#34;手动&#34;建立元组或者首先从元组开始。

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

答案 1 :(得分:3)

正如其他答案所说,在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),就可以编写完全通用的解决方案(并且可能涉及大量复制粘贴)。

答案 2 :(得分:2)

您可以编写转换运算符。

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 :(得分:1)

您可以手动执行此操作。例如:

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

答案 4 :(得分:0)

基于这些成员名称,即:第一个成员称为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<>,您可以使用此类成员(名为structab)从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>

如果您现在定义新的structBar,则为:

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

然后:

tuple_splitter<Bar> bar_tuple;

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

答案 5 :(得分:0)

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