以前、DateTimeライブラリを作ってて嵌ったこと。
Fusion Sequenceの最後尾に要素を追加するために、1要素のvectorを作ってjoinしようとしてました。
#include <boost/fusion/include/make_vector.hpp> #include <boost/fusion/include/join.hpp> #include <iostream> #include <boost/fusion/include/io.hpp> namespace fusion = boost::fusion; template <class Seq, class T> typename fusion::result_of::join<const Seq, const fusion::vector1<T> >::type push(const Seq& seq, const T& x) { return fusion::join(seq, fusion::make_vector(x)); } int main() { const fusion::vector<int, char> v(3, 'a'); std::cout << push(v, 3.14) << std::endl; }
(3 a 2.64195e-308)
はい、データが壊れます。
本来は、fusion::push_backを使えばいいのですが、push_back相当のことをjoinでやろうとすると、右辺がsingle viewではなく単なるvectorになってしまうので、オブジェクトの寿命が尽きてしまっているようです。
remember push_back!
#include <boost/fusion/include/make_vector.hpp> #include <boost/fusion/include/push_back.hpp> #include <iostream> #include <boost/fusion/include/io.hpp> namespace fusion = boost::fusion; template <class Seq, class T> typename fusion::result_of::push_back<const Seq, T>::type push(const Seq& seq, const T& x) { return fusion::push_back(seq, x); } int main() { const fusion::vector<int, char> v(3, 'a'); std::cout << push(v, 3.14) << std::endl; }
(3 a 3.14)
ちなみに、単なるpush_backの内部実装になりますが、joinでやる場合はsingle_viewを使ってこんな感じで書くことになります。
#include <boost/fusion/include/make_vector.hpp> #include <boost/fusion/include/join.hpp> #include <boost/fusion/include/single_view.hpp> #include <iostream> #include <boost/fusion/include/io.hpp> namespace fusion = boost::fusion; template <class Seq, class T> typename fusion::result_of::join<const Seq, const fusion::single_view<T> >::type push(const Seq& seq, const T& x) { return fusion::join(seq, fusion::single_view<T>(x)); } int main() { const fusion::vector<int, char> v(3, 'a'); std::cout << push(v, 3.14) << std::endl; }
(3 a 3.14)