在this和this问题中,我谈到(并提出了解决方案)来编写一个多功能记忆器。
这是我的解决方案:
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)
的责任是user2
与foo
使用的功能相同。
上一个解决方案的问题是user1
为enum
定义的user1
与foo
为同一函数定义的user2
无法匹配。
可能的解决方案:
如果不是enum
我们可以为每个函数定义一个“可能唯一”的密钥,例如SHA(functionName)
,那该怎么办?然后我们可以在文件中写入multiCache
对象和我们写(functionName,SHA(functioName))
的文本文件并将它们公开给user2
?可能效率低或不安全(除了相同sha码的概率很低)?