P0288R9: move_only_functionが待ち遠しく、似たようなもの(劣化版)を自作しようかどうかよく悩んでいます。そんな折、Boost.TypeErasureで簡単に作れるのではないかと思いつき、試していました。

その結果がこれです: https://wandbox.org/permlink/GwWCWR0PtF4XXqmh

#include <iostream>
#include <memory>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/callable.hpp>
#include <boost/type_erasure/relaxed.hpp>
 
template<typename T>
using function_t = boost::type_erasure::any<boost::mpl::vector<
    boost::type_erasure::relaxed,
    boost::type_erasure::constructible<boost::type_erasure::_self(boost::type_erasure::_self&&)>,
    boost::type_erasure::destructible<>,
    boost::type_erasure::callable<T>>>;
 
int main()
{
    auto p = std::make_unique<int>(100);
    auto q = std::make_unique<int>(200);
    function_t<void(std::unique_ptr<int>)> x([q = std::move(q)](std::unique_ptr<int> p) mutable
    {
        std::cout << *p << ' ' << *q << std::endl;
    });
    x(std::move(p));
}

コピー不可能な関数オブジェクトを格納することに成功はしています。ただ、TypeErasureのコードをぱっと読んだ感じ、どうも内部で無条件に動的メモリ確保する雰囲気なので、そこまで魅力的なやり方ではないなと思っています。move_only_functionでは、小サイズのオブジェクトを入れる際は動的メモリ確保をしないことが求められており、std::functionもそうなっています。

必ず動的メモリ確保するならstd::functionとstd::shared_ptrの組み合わせでなんとかする方法も考えられます。それとBoost.TypeErasureと完全自作とでどうするか、今日も迷っています。

スポンサード リンク

この記事のカテゴリ

  • ⇒ Boost.TypeErasureでmove_only_functionを模倣