#c #templates
#c #шаблоны
Вопрос:
Как я мог бы использовать некоторую структуру:
template<typename T>
typedef struct something_t {
int x;
int y;
T z;
} something_t;
И создайте тип утилиты (возможно, в сочетании с некоторыми макросами), который отображает его в структуру той же формы, но std::optionals
вместо этого заполненную. Другими словами, как бы я написал partial
структуру в следующем коде,
template<typename T>
struct partial<T> { using type = ??? };
template<typename T>
using partial_something_t = partial<something_t<T>>::type;
… что привело partial_something_t
бы к получению этого определения:
template<typename T>
typedef struct partial_something_t {
std::optional<int> x;
std::optional<int> y;
std::optional<T> z;
} partial_something_t;
Комментарии:
1. Для этого требуется отражение языка, которого нет в C . Вы могли бы достичь этого с помощью метапрограммирования.
2. Если бы я хотел также использовать макросы, помогло бы это?
3. Возможно, но это будет нелегко.
4. Вы можете сделать это с помощью кортежей:
std::tuple<Ts...>
может быть легко преобразован вstd::tuple<std::optional<Ts>...>
.5. Кстати
template<..> typedef
, это незаконно иtypedef struct
обычно не требуется в C .
Ответ №1:
Если вы управляете определением something_t
, вы можете изменить его таким образом:
template <template<typename> typename Wrapper, typename T>
struct new_something_t {
Wrapper<int> x;
Wrapper<int> y;
Wrapper<T> z;
};
Затем определите псевдоним:
template <typename What>
using Id = What;
Теперь ваш оригинал something_t<T>
становится new_something_t<Id, T>
и partial_something_t<T>
есть new_something_t<std::optional, T>
.
Комментарии:
1. Круто! Это выполнимо и позволяет избежать дублирования.
Ответ №2:
Один из способов добиться этого — использовать локальные включения с перегрузкой макросов. Создайте новый файл .inl.h, который содержит некоторую внутреннюю структуру следующим образом:
BEGIN_TEMPLATE_STRUCT(something_t)
DECLARE_MEMBER(int, x)
DECLARE_MEMBER(int, y)
DECLARE_MEMBER(T, z)
END_TEMPLATE_STRUCT
Затем создайте, возможно, два разных файла заголовков (или только один, как вам больше нравится), которые определяют конкретные определения макросов самостоятельно, используя push и pop_macro . Поместите push_macros прямо перед включением этого файла .inl.h с необработанным объявлением вашей структуры, включите файл, а затем не забудьте pop_macro, чтобы после этого получить чистое состояние. Затем первый заголовок определяет BEGIN_TEMPLATE_STRUCT как something_t, а второй заголовок — как partial_something_t и вложенные макросы в соответствии с вашими желаемыми конечными типами (DECLARE_MEMBER как std::optional …). Преимущество этого подхода заключается в том, что у вас есть минимальное базовое представление ваших данных, которое может быть адаптировано к более сложным. Основным недостатком является (подверженное ошибкам) само использование макросов и некоторая работа по написанию, по крайней мере, более сложных элементов, таких как типы методов.
Комментарии:
1. Если вы хотите изменить определение
something_t
, у C есть лучшие способы сделать это без каких-либо макросов.2. Нет, на определение something_t это не влияет, если вы правильно определяете макросы преобразования. Макрос выполняется именно так, как этого хочет MHebes. Наконец, у вас есть две разные структуры с желаемыми свойствами. C 17 может иметь некоторые приятные преимущества использования шаблонов (например, через кортежи), которые могут помочь здесь, но у него по-прежнему нет прямого способа для вторжения именованных членов, т. Е. Фактически отражения.
3. Макрос может выполняться, но он чертовски уродлив, инструменты будут подавляться им, и люди будут чесать головы, глядя на него.
4. По крайней мере, для простых структур большинство современных инструментов разработки работают здесь хорошо, поскольку вам не нужно, чтобы макрос был виден на стороне использования структуры / «внешнего мира». С минимальными усилиями по чистому размещению вы можете избежать здесь почти всех недостатков макросов. Но да, я признаю, что здесь всегда было бы лучше иметь какие-то подходы, основанные на языке.