【问题标题】:Initialize boost::fusion::map values初始化 boost::fusion::map 值
【发布时间】:2018-08-07 06:26:41
【问题描述】:

我有一个这样的boost::fusion::map

struct bar {};
struct baz {};

template<typename... Args>
struct foo
{
    foo(bar &, baz &) {}
};

template<typename... T>
using MapEntry = boost::fusion::pair<boost::mpl::set<T...>, foo<T...>>;

using Map = boost::fusion::map<
            MapEntry<int, bool, double>,
            MapEntry<std::string>,
            MapEntry<int64_t, uint32_t>,
            MapEntry<char, uint64_t>
            // ...
            >;

然后需要初始化Map 的实例,将bar_baz_ 传递给所有foo 构造函数。

目前,我有:

int main()
{
    bar bar_;
    baz baz_;

    Map map_(
        boost::fusion::make_pair<boost::mpl::set<int, bool, double>>(foo<int, bool, double>(bar_, baz_)),
        boost::fusion::make_pair<boost::mpl::set<std::string>>(foo<std::string>(bar_, baz_)),
        boost::fusion::make_pair<boost::mpl::set<int64_t, uint32_t>>(foo<int64_t, uint32_t>(bar_, baz_)),
        boost::fusion::make_pair<boost::mpl::set<char, uint64_t>>(foo<char, uint64_t>(bar_, baz_))
        // ...
    );

    return 0;
}

但这是非常多余的。是否有可能使这段代码更干净?

【问题讨论】:

  • 为什么你认为这是不可能的?你尝试了什么?你在哪里卡住了?
  • 目前我只找到Map map_( boost::fusion::make_pair&lt;boost::mpl::set&lt;int, bool, double&gt;&gt;(foo&lt;int, bool, double&gt;(bar_, baz_)), boost::fusion::make_pair&lt;boost::mpl::set&lt;std::string&gt;&gt;(foo&lt;std::string&gt;(bar_, baz_)), boost::fusion::make_pair&lt;boost::mpl::set&lt;int64_t, uint32_t&gt;&gt;(foo&lt;int64_t, uint32_t&gt;(bar_, baz_)), boost::fusion::make_pair&lt;boost::mpl::set&lt;char, uint64_t&gt;&gt;(foo&lt;char, uint64_t&gt;(bar_, baz_)) // ... );,但它太多余的解决方案

标签: c++ boost fusion


【解决方案1】:

首先创建一个函数来创建MapEntry

template<typename E, typename... Args>
E make_map_entry(Args &&...args)
{
    return boost::fusion::make_pair<E::first_type>(E::second_type(std::forward<Args>(args)...));
}

第二次创建一个函数来创建Map,它使用帮助函数为每个条目展开make_map_entry

template<typename M, std::size_t ...I, typename... Args>
M make_map_impl(std::index_sequence<I...>, Args &&...args)
{
    return M(make_map_entry<boost::fusion::result_of::value_at_c<M, I>::type>(std::forward<Args>(args)...)...);
}

template<typename M, typename... Args>
M make_map(Args &&...args)
{
    return make_map_impl<M>(std::make_index_sequence<boost::fusion::result_of::size<M>::value> {}, args...);
}

那么我们可以写

int main()
{
    bar bar_;
    baz baz_;

    Map map(make_map<Map>(bar_, baz_));

    return 0;
}

【讨论】:

    【解决方案2】:

    您可以使用自定义入口工厂:

    struct bound_factory {
        bar& bar_;
        baz& baz_;
    
        template <typename... T> auto entry() const {
             return boost::fusion::make_pair<boost::mpl::set<T...>>(foo<T...>(bar_, baz_));
        }
    };
    

    然后您可以按如下方式使用:

    Live On Coliru

    int main()
    {
        bar bar_;
        baz baz_;
    
        bound_factory f { bar_, baz_ };
    
        Map map_(
            f.entry<int, bool, double>(),
            f.entry<std::string>(),
            f.entry<int64_t, uint32_t>(),
            f.entry<char, uint64_t>()
        );
    }
    

    剪辑模式

    看起来您可能正在创建一个依赖注入框架。请注意这个相当不错的图书馆提案:Boost DI

    【讨论】:

    • 不错,但需要两次描述地图条目的类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    相关资源
    最近更新 更多