5

Short version:

I would like to be able to convert a struct to a tuple. At least the type. In the code below, the convertToTuple function does not work, because variadic parameters cannot be used in structured bindings (as far as I know). The key line is: auto& [values...] = value;

struct Vec3 {
 float x;
 float y;
 float z;
};
template <typename T>
auto structToTuple(T &value) {
 auto& [values...] = value;  //doesn't work
 return std::make_tuple<decltype(values)...>(values...);
}
Vec3 v;
std::tuple<float, float, float> t = structToTuple(v);

Basically, what I need is a means to convert the type of a custom structure to a tuple, which contains all of the types from the struct. For example:

struct Ray {Vec3, Vec3} -> std::tuple<
 std::tuple<float, float, float>,
 std::tuple<float, float, float>>;

Detailed problem:

I would like to create a templated function which takes a type or a list of types as template parameter and produces a list of textures, each texture containing an item. An other function can sample the texture list and pack the values back together to return the same type. For example, if I have a type:

std::pair<std::tuple<int, int>, int> value;
std::tuple<Texture<int, int>, Texture<int>> tex = createTexture(value);
std::pair<std::tuple<int, int>, int> thisshouldwork = sample(tex);

The above code is just a simple example of what I want to do, not my actual code. In this case 2 textures would be created, one texture would contain the two ints from the tuple, the other would hold a single int type. My intention is to hide the texture handling behind an interface, where I can store an arbitrary value (as long as it's composed of some simple types) in textures that I can upload to the GPU for the shaders. As long as I only use std::tuple, and std::pair, it does work, because I can extract the types from them:

template <typename... Args>
void f(std::tuple<Args...> t);

I would like to be able to do the same when the template parameter is a custom struct. For example:

struct Vec3 {
 float x;
 float y;
 float z;
};
Vec3 v;
Texture<float, float, float> tex = createTexture(v);

struct Ray{
 Vec3 pos;
 Vec3 dir;
};
Ray r;
std::tuple<Texture<float,float,float>, Texture<float,float,float>> tex2 = createTexture(r);

I am not convinced that this is even possibly with the current C++ standard, but based on the structured bindings, it seems possible. My idea would be something like this:

template <typename T>
auto structToTuple(T &value) {
 auto& [values...] = value;
 return std::make_tuple<decltype(values)...>(values...);
}
Vec3 v;
std::tuple<float, float, float> t = structToTuple(v);

As far as I am concerned variadic parameters only work function or template parameters. But if the structToTuple function would work, that would solve my problem.

Thanks for the help in advance, guys!

Update:

I have found a workaround for my problem (not a general solution): https://github.com/Dwarfobserver/AggregatesToTuples/blob/master/single_include/aggregates_to_tuples.hpp

The author of this library defined a structure to tuple conversion, but it only works if the structure has no more than 50 parameters. This solves my problem in practice, though I am still curious whether it is possible with an arbitrary structure.

Cœur
  • 37,241
  • 25
  • 195
  • 267
zazi
  • 71
  • 4
  • Sorry but isn't clear to me what do you want obtain, exactly. By example, from `struct foo { float a; float b; float c; };` what "texture" (?) do you exactly want? And from `struct bar { short a; int b; long c; long long d; };` – max66 Jun 17 '18 at 21:32
  • I think all the discussion about "textures" is really confusing the issue. You seem to want to extract some values in a struct into some other struct which can reconstruct the exact original struct. – Nicol Bolas Jun 17 '18 at 21:54
  • So you wanna have something like `f` based on the structs you described, how would you like to invoke `f`? Can you show me the full *pseudo code* revolving around that? – Dean Seo Jun 17 '18 at 23:23
  • What you want is called reflection and it's on the [agenda](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3814.html) of the committee. Until then indeed your workaround is possible (also have a look at magic_get). – rustyx Jun 18 '18 at 13:29
  • I think that I found something similar to what OP stated as the solution and wrote it up as an answer [here](https://stackoverflow.com/a/75672513/1667513). – nonsensickle Mar 08 '23 at 12:17

2 Answers2

2

You are missing the point of what structured bindings are designed to give you as a programmer. They are meant as a way to 'unpack' multiple parameters returned by a function in a way that makes it easy to address the individual parameters. At no time is the number of parameters unknown or variable.

https://en.cppreference.com/w/cpp/language/structured_binding

As mentioned in a comment above, there is a Reflection TS that is in the works (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4746.pdf), but at best that will provide the tools to create a solution for your need rather than be an out of the box solution. It is my understanding that the Reflection TS covers static reflection, where you can deduce the shape and contents of a type, rather than dynamic reflection where you can create types on the fly.

Mikel F
  • 3,567
  • 1
  • 21
  • 33
0

I think that the zpp::bits library does something similar to what OP has put as a solution to his/her problem, and I've mentioned a similar solution in an answer to another SO question.

nonsensickle
  • 4,438
  • 2
  • 34
  • 61