How should I be writing the get_filtered_graph in a generic way?

#include <map>
#include <string>
#include <vector>
#include <iostream>

#include <boost/graph/adjacency_list.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/graph_utility.hpp>

template <typename F> struct EdgeProperty {
    F features;

    EdgeProperty() = default;

    EdgeProperty(const F& f) : features(f) {}
};

template <typename EM, typename F>
struct filtered_edge {
    F filters;
    EM emap;

    filtered_edge() = default;
    filtered_edge(EM emap_, F filters_) : emap(emap_), filters(filters_) {}

    template <typename E> bool operator()(const E& e) {
        auto e_prop = get(emap, e);
        auto e_feat = e_prop.features;

        for (auto it: e_feat) {
            if (get(e_feat, it.first) != it.second) {
                return false;
            }
        }
        return true;
    }
};

template<typename G, typename F> G get_filtered_graph(G& g, F& filters) {
    typedef filtered_edge<boost::property_map<G, EdgeProperty<F> >, F> filter_fn;
    filter_fn filter{get(&EdgeProperty<F>::features, g), filters};
    boost::filtered_graph<G, filter_fn> fg(g, filter);
    return fg;
}

typedef std::map<std::string, int> dict;

typedef boost::adjacency_list<
        boost::vecS,
        boost::vecS,
        boost::directedS,
        boost::no_property,
        EdgeProperty<dict>
> Graph;

Graph create_empty_graph() noexcept {
    return {};
}

int main() {
    const char* name = "ABCDE";
    auto g = create_empty_graph();
    auto v0 = boost::add_vertex(g);
    auto v1 = boost::add_vertex(g);
    auto v2 = boost::add_vertex(g);

    dict d01;
    d01["a"] = 1;

    dict d12;
    d12["b"] = 1;

    dict fil;
    fil["a"] = 1;

    auto ep01 = EdgeProperty<dict>{
        dict{}
    };
    boost::add_edge(v0, v1, d01, g);
    boost::add_edge(v1, v2, d12, g);

    std::cout << "Before filter" << std::endl;
    boost::print_graph(g, name);
    auto fg = get_filtered_graph(g, fil);

    std::cout << "After filter" << std::endl;
    boost::print_graph(fg, name);

    Graph ga;
}