C++ 如何在C++;11
我制作了以下元组: 我想知道我应该如何迭代它?有C++ 如何在C++;11,c++,c++11,tuples,C++,C++11,Tuples,我制作了以下元组: 我想知道我应该如何迭代它?有tupl\u size(),但阅读文档时,我不知道如何使用它。我也有这样的搜索,但问题似乎围绕着Boost::tuple auto some = make_tuple("I am good", 255, 2.1); 模板 元组(常量std::tuple&tuple,F func,std::index\u序列)中的每个{ 使用expander=int[]; (void)扩展器{0,((void)func(std::get(tuple)),0)…};
tupl\u size()
,但阅读文档时,我不知道如何使用它。我也有这样的搜索,但问题似乎围绕着Boost::tuple
auto some = make_tuple("I am good", 255, 2.1);
模板
元组(常量std::tuple&tuple,F func,std::index\u序列)中的每个{
使用expander=int[];
(void)扩展器{0,((void)func(std::get(tuple)),0)…};
}
模板
元组中每个元组的无效值(常量std::tuple&tuple,F func){
对于数组中的每个数组(tuple,func,std::make_index_sequence());
}
用法:
auto some = std::make_tuple("I am good", 255, 2.1);
for_each_in_tuple(some, [](const auto &x) { std::cout << x << std::endl; });
autosome=std::make_tuple(“我很好”,255,2.1);
对于元组中的每一个(一些,[](const auto&x){std::cout,这里有一个类似且更详细的解决方案,它比T.C.给出的以前被接受的解决方案更容易理解(--它可能与网络中的数千个其他解决方案相同):
用法(与std::array一起使用
):
std::array some2={“还不错”,“你好世界”};
对于_each(some2,[](const auto&x){std::cout,这里尝试将对元组的迭代分解为组件部分
首先,一个表示按顺序执行一系列操作的函数。请注意,许多编译器发现这很难理解,尽管据我所知,这是合法的C++11:
template<class... Fs>
void do_in_order( Fs&&... fs ) {
int unused[] = { 0, ( (void)std::forward<Fs>(fs)(), 0 )... }
(void)unused; // blocks warnings
}
肉和土豆:
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
do_in_order( [&]{ f( get<Is>(std::forward<Tuple>(tup)) ); }... );
}
这并不需要太多赘述,但我个人觉得不太清楚。在我看来,do\u in\u order
的影子魔法是如何通过内联方式实现的
index\u sequence
(以及支持的模板)是C++14的一项功能,可以用C++11编写。在堆栈溢出上找到这样一个实现很容易。当前google最热门的是,如果我正确阅读注释,它可能是实际gccmake\u integer\u sequence至少一次迭代的基础(评论还指出了一些关于消除sizeof…
调用的编译时改进)
或者我们可以写:
template<class F, class...Args>
void for_each_arg(F&&f,Args&&...args){
using discard=int[];
(void)discard{0,((void)(
f(std::forward<Args>(args))
),0)...};
}
模板
每个参数(F&&F,参数&&…参数)的无效{
使用discard=int[];
(作废)放弃{0,((作废)(
f(标准:正向(参数))
),0)...};
}
然后:
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
for_each_arg(
std::forward<F>(f),
get<Is>(std::forward<Tuple>(tup))...
);
}
模板
每个元素的void(std::index\u序列、元组和元组、F和F){
使用std::get;
对于每个参数(
标准:正向(f),
获取(std::forward(tup))。。。
);
}
这避免了手动展开,但在更多编译器上编译。我们通过auto&&i
参数传递Is
在C++1z中,我们还可以使用std::apply
和for_each_arg
函数对象来消除索引篡改。取决于“迭代”后的计划在它上面。对不同类型的数据进行迭代对您意味着什么?我想cout
每个元素-最基本的迭代。访问cout
-ing的每个元素…就像这样?@MostafaTalebi:true…tuple
s可以保存异构类型,这些类型只能在编译器需要时在编译时进行索引根据类型适当地改变元素处理代码。非常不同。vector
、array
等都是同质容器,因此运行时迭代和处理不需要任何多态调度。+1但您应该提到,这只是c++14…(标题是c++11)。这是什么概念:[类后跟“…”然后是Tx],我不知道该怎么发音,我唯一能理解的是,它给出了元组值的变量参数,因为逻辑上正确的是,元组可能有不同的类型,但即使我希望有人能把我带到正确的地方,从那里我可以学到这一点?这些是变量模板:非常感谢@LauraMaftei.非常感谢T.CADL的get
是一个很好的方法。tuple\u size
也适用于数组和对,因此我不认为需要单独的get\u索引
重载-另外,->decltype(std::make\u index\u sequence())
-为什么要使用decltype
?@T.C.好吧,我开始使用auto
,然后通过将return
表达式移动到->
和return{}使其失效
。没有想到要摆脱decltype
。将其改为直接索引序列关闭元组大小,并消除重载。并且修复了一个打字错误(错过了一个…
)。@t.C.,雅克:你能解释一下为什么“ADL forget
”是一个“很好的操作”吗?与在函数调用中直接使用std::get
相比,有什么优势?@davidhigh因此,假设您定义自己的元组
-样结构(我不知道,是一个固定大小的矩阵类?)。如果我启用ADLstd::get
,并且您在您的类的名称空间中定义了自己的免费get
,那么我对get
的启用ADL的调用可能会访问它。您还必须专门化std::tuple_size
,但这种专门化是合法的。实际上,这只是试图作为一个例子编写过度通用的代码的问题习惯问题。它似乎使用了C++14的特性make_index_sequence。这可以根据在C++11中实现,但使该方法不如OP海报要求的那样对C++11有用。这不是C++11解决方案,而是C++1y解决方案。@EdwardZ.Yang:基本代码是C++11,只有带有通用lambda的示例需要C++14。但是谢谢你的回复@davidhigh,我一整天都在寻找解决方案,最终我得到了你的代码行。你救了我一天。真的谢谢你
template<class... Fs>
void do_in_order( Fs&&... fs ) {
int unused[] = { 0, ( (void)std::forward<Fs>(fs)(), 0 )... }
(void)unused; // blocks warnings
}
template<class T>
constexpr std::make_index_sequence<std::tuple_size<T>::value>
get_indexes( T const& )
{ return {}; }
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
do_in_order( [&]{ f( get<Is>(std::forward<Tuple>(tup)) ); }... );
}
template<class Tuple, class F>
void for_each( Tuple&& tup, F&& f ) {
auto indexes = get_indexes(tup);
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f) );
}
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
int unused[] = { 0, ( (void)f(get<Is>(std::forward<Tuple>(tup)), 0 )... }
(void)unused; // blocks warnings
}
template<class F, class...Args>
void for_each_arg(F&&f,Args&&...args){
using discard=int[];
(void)discard{0,((void)(
f(std::forward<Args>(args))
),0)...};
}
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
for_each_arg(
std::forward<F>(f),
get<Is>(std::forward<Tuple>(tup))...
);
}