gpt4 book ai didi

c++ - 不同签名函数的容器

转载 作者:太空狗 更新时间:2023-10-29 21:15:47 24 4
gpt4 key购买 nike

我正在尝试用 C++ 编写一个框架,用户可以在其中指示其程序中的一组函数,他想在其中应用 memoization。策略。

假设我们的程序 f1...f5 中有 5 个函数,我们希望避免对函数 f1 进行(昂贵的)重新计算,并且f3 如果我们已经用相同的输入调用了它们。 请注意,每个函数可以有不同的返回和参数类型。

我找到了 this问题的解决方案,但您只能使用 doubleint

我的解决方案

好的,我为我的问题编写了这个解决方案,但我不知道它是否高效、类型安全或者是否可以用更优雅的方式编写。

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;
}
}

最佳答案

这样的事情怎么样:

template <typename result_t, typename... args_t>
class Memoizer
{
public:
typedef result_t (*function_t)(args_t...);
Memoizer(function_t func) : m_func(func) {}

result_t operator() (args_t... args)
{
auto args_tuple = make_tuple(args...);

auto it = m_results.find(args_tuple);
if (it != m_results.end())
return it->second;

result_t result = m_func(args...);
m_results.insert(make_pair(args_tuple, result));
return result;
}

protected:
function_t m_func;
map<tuple<args_t...>, result_t> m_results;
};

用法是这样的:

// could create make_memoizer like make_tuple to eliminate the template arguments
Memoizer<double, double> memo(fabs);
cout << memo(-123.456);
cout << memo(-123.456); // not recomputed

关于c++ - 不同签名函数的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36759124/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com