在用户之间共享多类型地图

时间:2016-04-23 09:32:02

标签: c++ enums memoization

thisthis问题中,我谈到(并提出了解决方案)来编写一个多功能记忆器。

这是我的解决方案:

template <typename ReturnType, typename... Args>
function<ReturnType(Args...)> memoize(function<ReturnType(Args...)> func)
{
    return ([=](Args... args) mutable {
        static map<tuple<Args...>, ReturnType> cache;
        tuple<Args...> t(args...);
        auto result = cache.insert(make_pair(t, ReturnType{}));
        if (result.second) {
            // insertion succeeded so the value wasn't cached already
            result.first->second = func(args...);
        }
        return result.first->second;
    });
}

struct MultiMemoizator
{
    map<string, boost::any> multiCache;
    template <typename ReturnType, typename... Args>
    void addFunction(string name, function < ReturnType(Args...)> func) {
        function < ReturnType(Args...)> cachedFunc = memoize(func);
        boost::any anyCachedFunc = cachedFunc;
        auto result = multiCache.insert(pair<string, boost::any>(name,anyCachedFunc));
        if (!result.second)
            cout << "ERROR: key " + name + " was already inserted" << endl;
    }
    template <typename ReturnType, typename... Args>
    ReturnType callFunction(string name, Args... args) {
        auto it = multiCache.find(name);
        if (it == multiCache.end())
            throw KeyNotFound(name);
        boost::any anyCachedFunc = it->second;
        function < ReturnType(Args...)> cachedFunc = boost::any_cast<function<ReturnType(Args...)>> (anyCachedFunc);
        return cachedFunc(args...);
    }
};

这可能是主要的:

int main()
{
    function<int(int)> intFun = [](int i) {return ++i; };
    function<string(string)> stringFun = [](string s) {
        return "Hello "+s;
    };
    MultiMemoizator mem;
    mem.addFunction("intFun",intFun);
    mem.addFunction("stringFun", stringFun);
    try
    {
        cout << mem.callFunction<int, int>("intFun", 1)<<endl;//print 2
        cout << mem.callFunction<string, string>("stringFun", " World!") << endl;//print Hello World!
        cout << mem.callFunction<string, string>("TrumpIsADickHead", " World!") << endl;//KeyNotFound thrown
    }
    catch (boost::bad_any_cast e)
    {
        cout << "Bad function calling: "<<e.what()<<endl;
        return 1;
    }
    catch (KeyNotFound e) 
    {
        cout << e.what()<<endl;
        return 1;
    }
}

要在编译时使其安全,请在this回答作者建议使用(例如)a Key<int(int)>。该解决方案的问题是不能插入具有相同签名的两个功能。因此,正如this回答中的评论所提出的,我们可以枚举每个函数来唯一地标识每个函数。或者我们可以在struct Key中添加此枚举,以便我们可以保留类型安全性并唯一标识每个函数。

问题:

我想扩展此解决方案,以便不同用户可以使用它。因此,如果user1定义了一些函数int foo(int x)并在multiCache中记忆它,它可以在文件上写multiCache,而user2可以将它用于同一{ {1}}(显然int foo(int x)的责任是user2foo使用的功能相同。

上一个解决方案的问题是user1enum定义的user1foo为同一函数定义的user2无法匹配。

可能的解决方案:

如果不是enum我们可以为每个函数定义一个“可能唯一”的密钥,例如SHA(functionName),那该怎么办?然后我们可以在文件中写入multiCache对象和我们写(functionName,SHA(functioName))的文本文件并将它们公开给user2?可能效率低或不安全(除了相同sha码的概率很低)?

0 个答案:

没有答案