Структурированное связывание на неизвестной пользовательской структуре
Укороченная версия:
Я хотел бы иметь возможность преобразовать структуру в кортеж. По крайней мере, тип. В приведенном ниже коде функция convertToTuple не работает, поскольку переменные параметры не могут использоваться в структурированных привязках (насколько я знаю). Ключевая строка: auto & [values ...] = значение;
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);
По сути, мне нужно средство для преобразования типа пользовательской структуры в кортеж, который содержит все типы из структуры. Например:
struct Ray {Vec3, Vec3} -> std::tuple<
std::tuple<float, float, float>,
std::tuple<float, float, float>>;
Подробная проблема:
Я хотел бы создать шаблонную функцию, которая принимает тип или список типов в качестве параметра шаблона и создает список текстур, каждая текстура содержит элемент. Другая функция может сэмплировать список текстур и упаковать значения обратно, чтобы получить тот же тип. Например, если у меня есть тип:
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);
Приведенный выше код - просто простой пример того, что я хочу сделать, а не мой настоящий код. В этом случае будет создано 2 текстуры, одна из которых будет содержать два целых числа из кортежа, а другая будет содержать один тип int. Я намерен скрыть обработку текстур за интерфейсом, где я могу хранить произвольное значение (если оно состоит из нескольких простых типов) в текстурах, которые я могу загрузить в графический процессор для шейдеров. Пока я использую только std::tuple и std::pair, это работает, потому что я могу извлечь из них типы:
template <typename... Args>
void f(std::tuple<Args...> t);
Я хотел бы иметь возможность сделать то же самое, когда параметр шаблона является пользовательской структурой. Например:
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);
Я не уверен, что это возможно даже с текущим стандартом C++, но, основываясь на структурированных привязках, это кажется возможным. Моя идея была бы что-то вроде этого:
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);
Насколько мне известно, переменные параметры - это только рабочие функции или параметры шаблона. Но если функция structToTuple будет работать, это решит мою проблему.
Заранее спасибо за помощь, ребята!
Обновить:
Я нашел обходной путь для моей проблемы (не общее решение): https://github.com/Dwarfobserver/AggregatesToTuples/blob/master/single_include/aggregates_to_tuples.hpp
Автор этой библиотеки определил преобразование структуры в кортеж, но она работает только в том случае, если структура имеет не более 50 параметров. Это решает мою проблему на практике, хотя мне все еще интересно, возможно ли это с произвольной структурой.
2 ответа
Вам не хватает того, что структурированные привязки предназначены для вас как программиста. Они предназначены для "распаковки" нескольких параметров, возвращаемых функцией, таким образом, чтобы упростить обращение к отдельным параметрам. Ни в коем случае число параметров неизвестно или переменно.
https://en.cppreference.com/w/cpp/language/structured_binding
Как упомянуто в комментарии выше, в работах есть Reflection TS ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4746.pdf), но в лучшем случае это обеспечит инструменты для создания решения для ваших нужд, а не будет готовым решением. Насколько я понимаю, Reflection TS охватывает статическое отражение, где вы можете определить форму и содержание типа, а не динамическое отражение, где вы можете создавать типы на лету.
Я думаю, чтоzpp::bits
библиотека делает что-то похожее на то, что ОП предложил в качестве решения своей проблемы, и я упомянул подобное решение в ответе на другой вопрос SO .