C++ 我可以从向量数组初始化std::tuple吗?
我有一个包含变量类的std::vector。我想用相同的数据构造一个元组。这可能吗?元组的常规构造方法似乎有很大的限制C++ 我可以从向量数组初始化std::tuple吗?,c++,tuples,stdtuple,C++,Tuples,Stdtuple,我有一个包含变量类的std::vector。我想用相同的数据构造一个元组。这可能吗?元组的常规构造方法似乎有很大的限制 //In reality, I'm using JUCE::var. // SimpleVariant is here just to make the example code more explicit. struct SimpleVariant { SimpleVariant(int
//In reality, I'm using JUCE::var.
// SimpleVariant is here just to make the example code more explicit.
struct SimpleVariant
{
SimpleVariant(int i) : a(i), b("") {}
SimpleVariant(const std::string& s) : a(0), b(s) {}
operator int() const { return a; }
operator std::string() const { return b; }
private:
int a;
std::string b;
};
template <typename... T>
struct VariantTuple
{
VariantTuple(const std::vector<SimpleVariant>& v)
{
// how do I initialize the tuple here?
}
private:
std::tuple<T...> tuple;
};
std::vector<SimpleVariant> v{ SimpleVariant(1),
SimpleVariant(2),
SimpleVariant("a") };
VariantTuple<int, int, std::string> t (v);
//实际上,我使用的是JUCE::var。
//SimpleVariant在这里只是为了使示例代码更加明确。
结构简单变量
{
简单变量(inti):a(i),b(“”{}
SimpleVariant(const std::string&s):a(0),b(s){
运算符int()常量{返回a;}
运算符std::string()常量{return b;}
私人:
INTA;
std::字符串b;
};
模板
结构变量偶
{
变量偶(常量标准::向量和v)
{
//在这里如何初始化元组?
}
私人:
std::tuple;
};
向量v{SimpleVariant(1),
简单变量(2),
简单变量(“a”)};
变量t(v);
一些基于评论的澄清:
我不需要元组逐项匹配数组项,也不需要从给定数组推断类型。我想获取给定的数组,然后提取与特定类型匹配的变体。因此,例如,给定上述数组
v
,我希望能够构造一个VariantTuple
,并使其与术语“1”和“a”匹配。这引出了许多超出我最初问题范围的其他问题。但我现在感兴趣的问题是,是否有可能首先基于数组构造一个元组。我不确定您是否要求动态推断向量元素的数量并构造元组,这是不可能的,但现在开始。我使用了std::index_sequence
根据VariantTuple
的参数大小推断元组元素的数量。这需要C++17,因为它使用折叠表达式
#include <initializer_list>
#include <string>
#include <vector>
#include <tuple>
#include <utility>
#include <type_traits>
#include <ostream>
#include <iostream>
struct SimpleVariant
{
SimpleVariant(int i) : a(i), b("") {}
SimpleVariant(const std::string& s) : a(0), b(s) {}
operator int() const {
return a;
}
operator std::string() const {
return b;
}
int a;
std::string b;
};
template<typename V, size_t... dim, typename... Args>
auto populate_tuple(const V& vec, std::index_sequence<dim...>, const std::tuple<Args...>& t) {
return std::make_tuple(static_cast<std::remove_reference_t<decltype(std::get<dim>(t))>>(vec.at(dim))...);
}
template<size_t... dim, typename... Args>
std::ostream& dump_tuple(std::ostream& out, const std::tuple<Args...>& tpl, std::index_sequence<dim...>) {
((out << std::get<dim>(tpl) << ","), ...);
return out;
}
template<typename... T>
struct VariantTuple
{
VariantTuple(const std::vector<SimpleVariant>& v) : tpl(populate_tuple(v, std::make_index_sequence<sizeof...(T)>{}, tpl)) {}
template<typename... V>
friend std::ostream& operator <<(std::ostream& out, const VariantTuple<V...>& vt) {
return dump_tuple(out, vt.tpl, std::make_index_sequence<sizeof...(V)>{});
}
private:
std::tuple<T...> tpl;
};
int main() {
std::vector<SimpleVariant> v {
SimpleVariant(1),
SimpleVariant(2),
SimpleVariant("a")
};
VariantTuple<int, int, std::string> t (v);
std::cout << t << std::endl;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
结构简单变量
{
简单变量(inti):a(i),b(“”{}
SimpleVariant(const std::string&s):a(0),b(s){
运算符int()常量{
返回a;
}
运算符std::string()常量{
返回b;
}
INTA;
std::字符串b;
};
模板
自动填充\u元组(常量V和vec、std::index\u序列、常量std::元组和t){
返回std::make_tuple(static_cast(vec.at(dim))…);
}
模板
std::ostream和dump_tuple(std::ostream和out,const std::tuple和tpl,std::index_序列){
((问题标题提到数组,但问题测试和示例使用vector
s。你在问什么?如果结果元组作为函数参数而不是直接返回值给出,这是可能的,但它需要编译所有可能的类型排列,这会很快在变量大小中爆发。)e和向量长度。@chris你需要设置向量大小的上限来编译可能生成的每个元组。这不是很实用。但是你可以用std::array
来实现这一点。@FrançoisAndrieux,对,它适用于长度较低的情况,编译时间对较高的情况非常糟糕。你真的使用了吗ngSimpleVariant
或者它只是一个例子?你可以用std::variant
来代替吗?SimpleVariant
看起来很难用作variant
,这会使你想用它做的任何事情变得更加复杂。你已经构建了向量,不是吗?执行URL,我使用了用户-定义的转换运算符将t
更改为std::tuple&t
中的populate\u tuple
为我修复了它。它正在执行一个未初始化的tuple
的副本@FrançoisAndrieux,您需要通过引用传递该元组,我将编辑答案,gcc没有显示警告,clang显示了。这似乎很好,因为e更改为t
。但是将未初始化的tpl
作为参数传递给populate\u tuple
是一种代码气味,在任何代码检查中都会引起关注。也许您可以通过传递decltype(tpl)来传递tuple
改为模板参数,并使用std::tuple\u element\u t
代替decltype(std::get(t))>
。编辑:示例: