具有不同返回类型的成员函数的模板化别名

时间:2017-09-06 11:12:20

标签: c++ function templates alias member-functions

如果出现以下问题

    class a;
    class b;
    class c;
    class db {
        ...
        const std::set<a*>& get_all_a();
        const std::vector<b*>& get_all_b();
        const custom_c_container& obtain_all_the_cs();
        ...
    }

我有一个很长的函数,需要做类似的事情(我可以​​为这3个数据集中的每个数据集编写一个模板,它采用类型a,b或c),并且有一个db实例。唯一的问题是数据访问。我想通过写一些东西来解决这个问题:

    template<class data_type>
    auto get_data();

    template<>
    std::result_of<decltype(&db::get_all_a)(db)>::type get_data<a> 
        = std::mem_fn(&db::get_all_a);

这可能有多种原因导致失败,但我希望它确实展示了我想要实现的目标。

根据建议,我将添加一个所需的用法示例:

    template<class data_type>
    void process(db& my_db) {
        for(auto& item : get_data<data_type>(my_db) {
            //... some processing ...
        }
    }
    ...
    void process_all() {
        db my_db = get_db();
        process<a>(my_db);
        process<b>(my_db);
        process<c>(my_db);
    }

1 个答案:

答案 0 :(得分:1)

C ++ 17解决方案:

template <class data_type>
decltype(auto) get_data()
{
         if constexpr(std::is_same_v<data_type, a>) { return get_all_a(); }
    else if constexpr(std::is_same_v<data_type, b>) { return get_all_b(); }
    else                                            { return get_all_c(); }
} 

C ++ 14解决方案:

template <typename> 
struct dispatch;

template <> 
struct dispatch<a> { decltype(auto) get(db& x) { return x.get_all_a(); } };

template <> 
struct dispatch<b> { decltype(auto) get(db& x) { return x.get_all_b(); } };

template <> 
struct dispatch<c> { decltype(auto) get(db& x) { return x.get_all_c(); } };

template <class data_type>
decltype(auto) get_data()
{
    return dispatch<data_type>{}.get(db);
}

C ++ 11解决方案:

template <typename> 
struct dispatch;

template <> 
struct dispatch<a> 
{ 
    auto get(db& x) -> decltype(x.get_all_a()) { return x.get_all_a(); } 
};

template <> 
struct dispatch<b> 
{ 
    auto get(db& x) -> decltype(x.get_all_b()) { return x.get_all_b(); } 
};

template <> 
struct dispatch<c> 
{ 
    auto get(db& x) -> decltype(x.get_all_c()) { return x.get_all_c(); } 
};

template <class data_type>
auto get_data() -> decltype(dispatch<data_type>{}.get(db))
{
    return dispatch<data_type>{}.get(db);
}