在类中保留具有不同值类型的多个映射,并支持基于类型的查找

Hold multiple maps having different value types in a class and support type based lookup

本文关键字:类型 支持 于类型 查找 映射 保留      更新时间:2023-10-16

我想使用具有不同值类型的多个映射来实现异构存储。我正在根据值类型对地图进行索引。为此,我使用了打字列表。这是一个简化的例子。

我的type-list类如下所示。

namespace details
{
    struct null{};
    template<int N, typename E, typename T, typename ... Ts>
    struct index : index<N+1, E, Ts...> {};
    template<int N, typename E, typename ... Ts>
    struct index<N, E, E, Ts...>
    {
        constexpr static int value = N;
    };
    template<int N, typename E>
    struct index<N, E, null>
    {
        constexpr static int value = -1;
    };
}
template<typename ... Ts>
struct typelist
{
    using type = typelist<Ts...>;
    template<typename T>
    struct index : details::index<0, T, Ts..., details::null> {};
};

存储类实现如下,一个包含T类型值的模板类。

#include <iostream>
#include <tuple>
#include <typeinfo>
#include <map>

template<typename T>
struct storage_impl
{
    //storage_impl(storage_impl const &) = delete;
    bool try_getting(int key, T &value)
    {
        auto search = _storage.find(key);
        if(search != _storage.end() )
        {
            value = search->second;
            return true;
        }
        return false;   
    }
    std::map<int,T> _storage;
};

最后,存储管理器看起来像是,它有几个storage_impl实例,我想根据类型对它们进行索引。

struct storage_manager{
    // tuple storing different storage_impls
    std::tuple< storage_impl<double> , storage_impl<std::string> > storages { storage_impl<double>{},storage_impl<std::string>{} };
    using item_types = typelist<double,std::string>;
    storage_manager(){}
    ~storage_manager(){}
    storage_manager(storage_manager const &) = delete;
    template<typename T>
    bool try_getting(int key, T &value)
    {
        return std::get<item_types::index<T>::value>(storages).try_getting(key,value);
    }
};
int main()
{ 
    storage_manager  mgr;
    double val1;
    std::cout<<mgr.try_getting(123,val1);
}

直到storage_impl变成copyable,一切都会起作用。但我希望storage_implnon-copyable

如何在我的storage_implnon-copyable的情况下实现这一点。

附言-不想使用相同的继承。

以下是我的工作代码,我已经声明cache_impls为成员变量,并为每种情况指定了专用函数storage_ref。我只实现了try_get,其他功能可以使用storage_ref来实现。

#include <iostream>
#include <tuple>
#include <map>
#include <boost/noncopyable.hpp>
template<typename T>
struct storage_impl : public boost::noncopyable
{
    storage_impl(){}
    ~storage_impl(){}
    bool try_getting(int key, T &value)
    {
        auto search = _storage.find(key);
        if(search != _storage.end() )
        {
            value = search->second;
            return true;
        }
        return false;   
    }
    bool try_setting(int key, T const &value)
    {
        auto search = _storage.insert(std::make_pair(key,value));
        if(search.second == true )
        {
            return true;
        }
        return false;   
    }
    bool exists(int key)
    {
        auto search = _storage.find(key);
        if(search != _storage.end() )
        {
            return true;
        }
        return false; 
    }
    std::map<int,T> _storage;
};
struct storage_manager  : public boost::noncopyable
{
    storage_impl<double> double_store;
    storage_impl<std::string> string_store;
    template<typename T>
    struct item_return{ using type = storage_impl<T>; };
    template<typename T>
    typename item_return<T>::type storage_ref();
    template<typename T> 
    bool try_getting(int key, T &value)
    {
        return storage_ref<T>().try_getting(key,value);
    }
    template<typename T> 
    bool try_setting(int key, T const &value)
    {
        return storage_ref<T>().try_setting(key,value);
    }
    template<typename T> 
    bool exists(int key)
    {
        return storage_ref<T>().exists(key);
    }
    storage_manager(){}
    ~storage_manager(){}
};

//double specialization
template<>
struct storage_manager::item_return<double>{ using type = storage_impl<double>&; };
template<>
inline storage_impl<double>& storage_manager::storage_ref<double>()
{
    return double_store;
}
//std::string specialization
template<>
struct storage_manager::item_return<std::string>{ using type = storage_impl<std::string>&; };
template<>
inline storage_impl<std::string>& storage_manager::storage_ref<std::string>()
{
    return string_store;
}
int main()
{
    storage_manager mgr;
    double val1 = 90;
    std::cout<<mgr.try_getting(123,val1)<<'n';
    std::cout<<mgr.try_setting(123,val1)<<'n';
    std::cout<<mgr.exists<double>(123)<<'n';
    std::string val2;
    std::cout<<mgr.try_getting(123,val2)<<'n';  
}

期待其他选择。。。