Boost.Phoenix V3でのmove
例えば common.hpp を次のように書いたとする。
#include <boost/move/move.hpp> struct S { BOOST_MOVABLE_BUT_NOT_COPYABLE(S) public: S() {} S(BOOST_RV_REF(S)) {} }; void f(S) {}
で、このSをfにmoveしてみる。
#include "common.hpp" #include <boost/move/move.hpp> int main() { S s; f(boost::move(s)); }
まぁここまでは当然動く。
で、ここから本題。上のコードをBoost.Phoenix化したくて下のように書いてみても当然エラーになる。
#include "common.hpp" #include <boost/phoenix/core.hpp> #include <boost/phoenix/bind.hpp> int main() { S s; boost::phoenix::bind(f, boost::move(s))(); }
まぁこれは何となく分かるわけで、例えばreference_wrapperみたいに
#include "common.hpp" #include <boost/phoenix/core.hpp> #include <boost/phoenix/bind.hpp> #include <boost/ref.hpp> template <typename T> struct rvref { rvref(T &value) : value(&value) {} operator BOOST_RV_REF(T)() const { return boost::move(*value); } public: T *value; }; int main() { S s; rvref<S> rvs(s); boost::phoenix::bind(f, boost::ref(rvs))(); }
って適当に書いてもよくわからないがC++11でしか通らない。
C++11だけで通っても結局は
@Flast_RO いえ、単に Boost.Phoenix だとコンパイルが Boooost してしまうので lambda を使っているだけですね。 Boost.Phoenix と C++11 の相性に関してはよく知りません。
2012-06-28 11:38:17 via web to @Flast_RO
なわけで、、、、
まぁMotivationとしては同じコードで03/11で動いて欲しいと。ライブラリコードだとそうなりますね。まぁBOOST_NO_LAMBDASでdispatchしてもいいですけど。
どちらにせよmoveっぽい何かは欲しいわけで、仕方ないから書いた。
https://github.com/Flast/boost.mmm/blob/master/boost/mmm/detail/phoenix/move.hpp
そうするとこうなるわけで、
#include "common.hpp" #include <boost/phoenix/core.hpp> #include <boost/phoenix/bind.hpp> #include <boost/mmm/detail/phoenix/move.hpp> #include <boost/ref.hpp> int main() { S s; boost::phoenix::bind(f, boost::mmm::detail::phoenix::move(boost::ref(s)))(); }
結局BOOST_NO_RVALUE_REFERENCEで分岐するぐらいだったらlambdaで分岐しても良かったかもしれないと今更ながら思ってる。
とはいえrv-refあってもlambdaないclang 3.0とかあるわけで、結局必要か。