如何为Hana序列写一个for循环? [英] How to write a for loop for a Hana sequence?
问题描述
我有一个Boos.Hana序列,我想打印它到屏幕,用逗号分隔。但是逗号只分开元素,所以我必须检查我是否在最后一个元素。
目前我的黑客是非常糟糕的(看着指针,并转换到 void *
。
template< class P,class ... Ts>
decltype(auto)operator<<(
std :: ostream& os,
boost :: hana :: tuple< Ts ...> const& tpl
){
os<<{;
boost: :hana :: for_each(
tpl,[& x] {
os<< x;
if((void *)&boost; hana: :back(tpl)!=(void *)& x)os<<,;
}
);
return os< b $ b}
在Boost.Fusion的情况下,它更复杂,因为我使用融合迭代器 boost :: fusion :: begin
和 boost :: fusion :: end
),但至少我可以比较迭代器。( bool last = result_of :: equal_to< typename result_of :: next< First> :: type,Last> :: value
)。
另一种提出这个问题的方法是如果在Hana中有(meta)迭代器。
,为了回答你的意见, drop_back
确实做了一个副本。 Hana中的所有算法都制作副本,并且渴望,如此处所述。 p>
其次,您可以使用 hana :: intersperse
在每个元素之间添加逗号,导致类似
template< class P,class ... Ts>
decltype(auto)operator<<(
std :: ostream& os,
boost :: hana :: tuple< Ts ...> const& tpl
) {
os<< {;
boost :: hana :: for_each(boost :: hana :: intersperse(tpl,,),
[&](auto const& x){
os< ; x;
});
return os<< };然而,最好的解决方案可能是使用
}
< experimental :: print ,这完全符合您的需求:
#include< boost / hana /experimental/printable.hpp>
#include< boost / hana / tuple.hpp>
#include< iostream>
int main(){
auto ts = hana :: make_tuple(1,2,3);
std :: cout<< hana :: experimental :: print(ts);
}
/ strong>
如果要使用 intersperse
解决方案,但不想复制可以执行以下操作:
#include< boost / hana.hpp>
#include< functional>
#include< iostream>
namespace hana = boost :: hana;
template< class ... Ts>
decltype(auto)operator<<(std :: ostream& os,hana :: tuple< Ts ...> const& tpl){
os& {;
char const * sep =,;
auto refs = hana :: transform(tpl,[](auto const& t){return std :: ref(t);});
hana :: for_each(hana :: intersperse(refs,std :: ref(sep)),
[&](auto const& x){
os<< x .get();
});
return os<< };
}
但实际上你应该使用 hana: :experimental :: print
。如果你的用例是性能关键的,你想避免创建一个 std :: string
,我会质疑 std :: ostream
。
编辑结束
I have a Boos.Hana sequence and I would like to print it to screen separated by commas. However the commas separate elements only, so I have to check if I am at the last element.
Currently my hack is pretty bad (looking at the pointer and casting to void*
.
template<class P, class... Ts>
decltype(auto) operator<<(
std::ostream& os,
boost::hana::tuple<Ts...> const& tpl
){
os << "{";
boost::hana::for_each(
tpl, [&](auto& x){
os << x;
if((void*)&boost::hana::back(tpl) != (void*)&x) os << ", ";
}
);
return os << "}";
}
In the case of Boost.Fusion it was more complicated because I use fusion iterators (boost::fusion::begin
and boost::fusion::end
) but at least I could compare the iterators. (bool last = result_of::equal_to<typename result_of::next<First>::type, Last>::value
).
Another way to ask this question is if there are (meta) iterators in Hana.
First, to answer your comment, drop_back
does make a copy. All algorithms in Hana make copies and are eager, as documented here.
Secondly, you could use hana::intersperse
to add a comma between each element, resulting in something like
template<class P, class... Ts>
decltype(auto) operator<<(
std::ostream& os,
boost::hana::tuple<Ts...> const& tpl
){
os << "{";
boost::hana::for_each(boost::hana::intersperse(tpl, ", "),
[&](auto const& x){
os << x;
});
return os << "}";
}
However, the best solution would probably be to use experimental::print
, which does exactly what you want:
#include <boost/hana/experimental/printable.hpp>
#include <boost/hana/tuple.hpp>
#include <iostream>
int main() {
auto ts = hana::make_tuple(1, 2, 3);
std::cout << hana::experimental::print(ts);
}
Edit
If you want to use the intersperse
solution, but do not want to make a copy of the sequence, you can do the following:
#include <boost/hana.hpp>
#include <functional>
#include <iostream>
namespace hana = boost::hana;
template <class... Ts>
decltype(auto) operator<<(std::ostream& os, hana::tuple<Ts...> const& tpl) {
os << "{";
char const* sep = ", ";
auto refs = hana::transform(tpl, [](auto const& t) { return std::ref(t); });
hana::for_each(hana::intersperse(refs, std::ref(sep)),
[&](auto const& x){
os << x.get();
});
return os << "}";
}
But really, you should probably be using hana::experimental::print
. And if your use case is performance critical and you want to avoid creating a std::string
, I would question the usage of std::ostream
in the first place.
End of edit
这篇关于如何为Hana序列写一个for循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!