我有一个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, [&](auto& x){
os << x;
if((void*)&boost::hana::back(tpl) != (void*)&x) os << ", ";
}
);
return os << "}";
}
在Boost.Fusion的情况下,它更加复杂,因为我使用了融合迭代器(
boost::fusion::begin
和boost::fusion::end
),但至少我可以比较这些迭代器。 (bool last = result_of::equal_to<typename result_of::next<First>::type, Last>::value
)。提出此问题的另一种方法是,在Hana中是否有(元)个迭代器。
最佳答案
首先,为了回答您的评论,drop_back
会进行复制。 Hana中的所有算法都会复制并渴望,如here所述。
其次,您可以使用 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);
}
编辑
如果要使用
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
的用法。编辑结束
关于c++ - 如何为Hana序列编写for循环?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34702694/