Как обрабатывать вложенные структуры в шаблонах в сгенерированном коде отражения

#c #template-meta-programming

#c #шаблон-мета-программирование

Вопрос:

Я пытаюсь создать библиотеку отражения C . Цель состоит в том, чтобы использовать анализатор clang для генерации набора метаданных из файлов заголовков для создания файлов заголовков meta, которые могут быть включены для выполнения определенных отражающих операций. Я использовал класс Meta_data, который становится специализированным для каждого типа в файле заголовка, и он довольно хорошо работает для конкретных типов, но не работает для вложенных структур внутри типов шаблонов.

Вот пример:

 
// header.h
struct foo
{
  int member1;
  int member2;
  struct nested
  {
    int member;
  };
};

template <int val>
struct template_foo
{
  int member;
  struct nested
  {
    int member;
  };
};

// meta/header.h

#include <tuple>
#include <utility>
template <typename T>
struct Meta_data
{
  static_assert(sizeof(T) != 0, "Must be specialized");
};

template <>
struct Meta_data<foo>
{
  constexpr auto tuple_view(fooamp; object)
  {
    return std::forward_as_tuple(object.member1, object.member2);
  }
};

template <>
struct Meta_data<foo::nested>
{
  constexpr auto tuple_view(foo::nestedamp; object)
  {
    return std::forward_as_tuple(object.member);
  }
};

template <int val>
struct Meta_data<template_foo<val>>
{
  constexpr auto tuple_view(template_foo<val>amp; object)
  {
    return std::forward_as_tuple(object.member);
  }
};

// This fails 
//
// template <int val>
// struct Meta_data<typename template_foo<val>::nested>
// {
//   constexpr auto tuple_view(template_foo<val>::nestedamp; object)
//   {
//     return std::forward_as_tuple(object.member);
//   }
// };
//
//
// GCC 10.2.0 Error output
// test.cpp:56:8: error: template parameters not deducible in partial specialization:
//    56 | struct Meta_data<typename template_foo<val>::nested>
//       |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// test.cpp:56:8: note:         ‘val’

// test.cpp
int main()
{
  
}
  

Я понимаю ошибку компилятора, но я не могу придумать другого способа заставить это работать. Цель состоит в том, чтобы иметь возможность принимать любой тип и просматривать его члены как кортеж, например:

 std::get<0>(Meta_data<some_struct>::tuple_view(some_struct_instance));
  

Есть ли способ перепроектировать мой Meta_class, чтобы я мог получить желаемое конечное поведение даже для вложенных структур в шаблонных структурах / классах?

Комментарии:

1. Подобные вещи предпринимались неудачно в течение десятилетий. Наиболее знакомый мне пример — это мета-объектный компилятор Qt. Обычно нет хорошего способа решить эту проблему без поддержки компилятора. Вот почему правильное отражение должно быть особенностью языка, и несколько умных людей C стремятся стандартизировать его.

2. Плагины компилятора довольно полезны для этого, и я лично пробовал их в прошлом. Это определенно работает, но для правильного выполнения требуется очень и очень много усилий.