Я разрабатываю библиотеку C++, которая считывает CSV-файл с данными из некоторого эксперимента и выполняет некоторую агрегацию и выводит код pgfplots. Я хочу сделать библиотеку максимально простой и простой в использовании. Я также хочу выделить его из типов данных, которые представлены в файле CSV, и оставить возможность пользователю анализировать каждый столбец по своему желанию. Я также хочу избежать Boost Spirit Qi или другого сильного сильного анализатора.Как построить кортеж из массива
Простым решением для пользователя является создание типа для каждого столбца с конструктором, который принимает «char *». Конструктор выполняет собственный синтаксический анализ для заданного значения, которое является одной ячейкой данных. Затем пользователь передает мне список типов; схема, представляющая типы в строке данных. Я использую этот список типов для создания кортежа, в котором каждый член кортежа отвечает за синтаксический анализ.
Проблема заключается в том, как инициализировать (построить) этот кортеж. Разумеется, обращение с кортежами не так просто, поскольку итерация по их элементам в основном выполняется во время компиляции. Сначала я использовал Boost Fusion для достижения этой задачи. Однако функция, которую я использовал (преобразование), хотя может принимать кортеж как вход (с соответствующим адаптером), похоже, что он не возвращает кортеж. Мне нужно, чтобы возвращаемое значение являлось кортежем, поэтому какой-то другой код может использовать его как ассоциативный контейнер типа-к-значению (доступ к нему по типу через std::get<T>
) при использовании только стандартных инструментов, то есть без использования Boost. Поэтому мне пришлось преобразовать все преобразования Fusion в std :: tuple.
Мой вопрос заключается в том, как избежать этого преобразования, и еще лучше, как избежать Boost Fusion полностью.
Простым решением, которое приходит на ум, является использование конструктора std :: tuple и каким-то образом передать каждому элементу его соответствующую «const *», которую он должен построить. Однако, хотя это возможно, используя некоторые сложные методы перечисления на основе шаблонов, мне интересно, существует ли простой подход с параметром-пакетом или даже более простой способ передать значения конструкторам отдельных элементов кортеж.
Чтобы уточнить, что я ищу, любезно ознакомьтесь с этим следующим кодом.
#include <cstdio>
#include <array>
template <typename...> struct format {};
template <typename...> struct file_loader {};
template <typename... Format>
struct
file_loader<format<Format...> > {
void load_file() {
size_t strsize = 500u;
char *str = new char[strsize]();
auto is = fopen("RESULT","r");
/* example of RESULT:
dataset2,0.1004,524288
dataset1,0.3253,4194304
*/
while(getline(&str, &strsize, is) >= 0) {
std::array<char*, 3> toks{};
auto s = str;
int i = 2;
while(i --> 0)
toks[i] = strsep (&s, ",");
toks[2] = strsep (&s, ",\n");
std::tuple<Format...> the_line{ /* toks */ } ; // <-- HERE
//// current solution:
// auto the_line{
// as_std_tuple(// <-- unnecessary conversion I'd like to avoid
// boost::fusion::transform(boost::fusion::zip(types, toks), boost::fusion::make_fused(CAST()))
// )};
// do something with the_line
}
}
};
#include <string>
class double_type {
public:
double_type() {}
double_type(char const *token) { } // strtod
};
class int_type {
public:
int_type() {}
int_type(char const *token) { } // strtoul
};
int main(int argc, char *argv[]) {
file_loader< format< std::string,
double_type,
int_type > >
{}.load_file();
return 0;
}
Я выделил интересную строку как «ЗДЕСЬ» в комментарии.
Мой вопрос именно это:
Есть ли способ построить экземпляр станд :: кортеж (разнородных типов, каждый из которых неявно преобразованы из «полукокса *») с автоматической продолжительности хранения (в стеке) от
std::array<char *, N>
, где N равно размеру этого кортежа?
Ответ Я ищу должен
- Избегайте подталкивания Fusion
- (Простота условие) Избегайте использования более чем 5 строк шаблонного шаблонов на основе кода перечисления
- С другой стороны, показывает, почему это невозможно сделать в стандарте C++ 14
Ответ может использовать конструкторы C++ 17, я бы не прочь.
Спасибо,
Было бы хорошо знать, может ли преобразование Fusion напрямую возвращать std :: tuple. –
'while (i -> 0)' Пожалуйста, не делайте этого. Вы будете пугать детей. :) – erip
@erip Я на самом деле не использую это. В моем реальном коде я использую boost irange. Я просто не хотел приносить все нестандартные вещи и включает в себя мой код здесь. Разве вы не думаете, что иранге будет страшнее? –