Как я могу перебирать упакованный список аргументов вариативного шаблона?

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

Общая идея состоит в том, чтобы перебирать список, сохранять все данные типа int в вектор, хранить все данные типа char * в векторе и сохранять все данные типа float в векторе. Во время этого процесса также должен быть отдельный вектор, в котором хранятся отдельные символы того порядка, в котором были введены аргументы. Например, когда вы нажимаете push_back (a_float), вы также выполняете push_back ('f'), который просто сохраняет отдельный символ, чтобы знать порядок данных. Я мог бы также использовать здесь std :: string и просто использовать + =. Вектор просто использовался в качестве примера.

Теперь эта вещь спроектирована так, что сама функция построена с использованием макроса, несмотря на злые намерения, это необходимо, поскольку это эксперимент. Таким образом, буквально невозможно использовать рекурсивный вызов, поскольку фактическая реализация, которая будет содержать все это, будет расширена во время компиляции; и вы не можете повторно использовать макрос.

Несмотря на все возможные попытки, я все еще не могу понять, как это сделать. Поэтому вместо этого я использую более запутанный метод, который включает в себя создание типа и передачу этого типа в шаблон varadic, расширение его внутри вектора, а затем просто повторение этого. Однако я не хочу вызывать такую ​​функцию, как:

foo(arg(1), arg(2.0f), arg("three");

Итак, настоящий вопрос в том, как я могу обойтись без нее? Чтобы вы, ребята, лучше понимали, что на самом деле делает код, я вставил оптимистичный подход, который использую сейчас.

struct any {
  void do_i(int   e) { INT    = e; }
  void do_f(float e) { FLOAT  = e; }
  void do_s(char* e) { STRING = e; }

  int   INT;
  float FLOAT;
  char *STRING;
};


template<typename T> struct get        { T      operator()(const any& t) { return T();      } };
template<>           struct get<int>   { int    operator()(const any& t) { return t.INT;    } };
template<>           struct get<float> { float  operator()(const any& t) { return t.FLOAT;  } };
template<>           struct get<char*> { char*  operator()(const any& t) { return t.STRING; } };

#define def(name)                                  \
  template<typename... T>                          \
  auto name (T... argv) -> any {                   \
   std::initializer_list<any> argin = { argv... }; \
    std::vector<any> args = argin;
#define get(name,T)  get<T>()(args[name])
#define end }

any arg(int   a) { any arg; arg.INT    = a; return arg; }
any arg(float f) { any arg; arg.FLOAT  = f; return arg; }
any arg(char* s) { any arg; arg.STRING = s; return arg; }

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

def(foo)
  int data = get(0, int);
  std::cout << data << std::endl;
end

очень похож на python. он тоже работает, но проблема только в том, как вы вызываете эту функцию. Вот краткий пример:

foo(arg(1000));

От меня требуется создать новый любой тип, что очень эстетично, но это не значит, что эти макросы тоже не являются. Помимо этого, я просто хочу сделать следующее: foo (1000);

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

Также следует отметить, что я хорошо понимаю, что это не совсем дружественно к типу, поскольку я поддерживаю только int, float, char *, и это меня устраивает. Мне больше ничего не требуется, и я добавлю проверки для использования type_traits, чтобы убедиться, что переданные аргументы действительно являются правильными, чтобы вызвать ошибку времени компиляции, если данные неверны. Это не проблема. Мне также не нужна поддержка чего-либо, кроме этих типов POD.

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

Спасибо за ваше внимание, и я с нетерпением жду помощи.

50
задан Jichao 24 November 2013 в 01:07
поделиться