如何从数组构造元组 [英] How to construct a tuple from an array
问题描述
我正在设计一个C ++库,该库从一些实验中读取报告数据的CSV文件,并进行一些汇总并输出pgfplots代码。我想使该库尽可能通用并且易于使用。我还想将其与CSV文件中表示的数据类型隔离,并让用户根据需要选择分析每一列的选项。我也想避免使用Boost Spirit Qi或其他重型解析器。
I am designing a C++ library that reads a CSV file of reported data from some experiment and does some aggregation and outputs a pgfplots code. I want to make the library as generic and easy to use as possible. I also want to isolate it from the data types that are represented in the CSV file and leave the option to user to parse each column as she desires. I also want to avoid Boost Spirit Qi or other heavy duty parser.
我拥有的简单解决方案是让用户为每个列创建一个类型,并使用一个构造函数取 char *。构造函数对其给定的值进行自己的解析,该值是数据中的一个单元格。然后,用户将类型列表传递给我;模式,代表一行数据中的类型。我使用此类型列表创建一个元组,其中元组的每个成员都负责解析自身。
The simple solution I have is for the user to create a type for each column, with a constructor that takes "char *". The constructor does its own parsing for the value it is given, which is one cell from the data. The user then passes me a list of types; the schema, representing the types in a line of data. I use this type list to create a tuple, in which every member of the tuple is responsible for parsing itself.
现在的问题是如何初始化(构造)该元组。当然,处理元组并不是一件容易的事,因为遍历元组的元素主要是编译时操作。我最初使用Boost Fusion来完成此任务。但是,我使用的函数(转换)虽然可能将元组作为输入(使用适当的适配器),但它似乎未返回元组。我需要将返回值设为元组,以便其他代码可以将其用作关联的类型到值容器(通过 std :: get< T>
),而仅使用标准工具,即不使用Boost。因此,我必须将Fusion的返回值转换为std :: tuple。
The problem now is how to initialise (construct) this tuple. Dealing with tuples is of course not straightforward since iterating over their elements is mostly a compile-time operation. I used Boost Fusion at first to achieve this task. However, the function I used (transform) although might take a tuple as input (with the appropriate adapter), it does not seem to return a tuple. I need the return value to be a tuple so some other code can use it as an associative type-to-value container (access it by type via std::get<T>
), while using only standard tools, that is, without using Boost. So I had to convert whatever Fusion's transform returned into std::tuple.
我的问题是如何避免这种转换,更好的是如何完全避免Boost Fusion。
My question is how to avoid this conversion, and better yet how to avoid Boost Fusion completely.
想到的一个简单解决方案是使用std :: tuple的构造函数,并以某种方式将每个需要传递的元素 const *传递给它。但是,尽管可以使用一些复杂的基于模板的枚举技术来实现,但我想知道是否存在一种简单的类似于参数打包的方法,还是将值传递给a的各个元素的构造函数的更简单方法元组。
A simple solution that comes to mind is to use the constructor of std::tuple, and somehow pass each element its respective "const *" that it needs to construct. However, while this is possible using some complicated template-based enumeration techniques, I am wondering if there is a straightforward "parameter-pack"-like approach, or an even simpler way to pass the values to the constructors of the individual elements of a tuple.
为阐明我要查找的内容,请看以下这段代码。
To clarify what I am seeking, kindly take a look at this following code.
#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;
}
我在评论中将有趣的行突出显示为 HERE。
I've highlighted the interesting line as "HERE" in a comment.
我的问题正好是:
有没有一种构造std的方法:: tuple实例(具有不同类型的
类型,每种类型都可以从 char *隐式转换),并具有
自动存储持续时间(在堆栈上),该存储时间来自std :: array< ; char *,N>
,
其中N等于该元组的大小?
Is there a way to construct a std::tuple instance (of heterogeneous types, each of which is implicitly convertible from "char *") with automatic storage duration (on the stack) from a
std::array<char *, N>
, where N equals the size of that tuple?
我正在寻找的答案应该
- 避免Boost Fusion
- (简单性条件)避免使用大于5行基于样板模板的枚举代码
- 或者,显示了为什么在C ++ 14标准中无法做到这一点
答案可以使用C ++ 17构造,我不在乎。
The answer can use C++17 constructs, I wouldn't mind.
谢谢,
推荐答案
与所有涉及 std :: tuple
,使用 index_sequence
为您提供参数包以使用以下方式对数组建立索引:
As with all questions involving std::tuple
, use index_sequence
to give you a parameter pack to index the array with:
template <class... Formats, size_t N, size_t... Is>
std::tuple<Formats...> as_tuple(std::array<char*, N> const& arr,
std::index_sequence<Is...>)
{
return std::make_tuple(Formats{arr[Is]}...);
}
template <class... Formats, size_t N,
class = std::enable_if_t<(N == sizeof...(Formats))>>
std::tuple<Formats...> as_tuple(std::array<char*, N> const& arr)
{
return as_tuple<Formats...>(arr, std::make_index_sequence<N>{});
}
您将使用哪种方式:
std::tuple<Format...> the_line = as_tuple<Format...>(toks);
这篇关于如何从数组构造元组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!