Joh*_*per 6 c++ templates lazy-evaluation visual-c++ c++11
我想创建一个模板类,它可以存储该函数的函数指针和参数,以便稍后可以使用此参数调用该函数.
我想普遍写这个,而不是依赖于参数类型或数字.
以下是使用c ++ 11的可变参数模板的想法:
template<class T, typename... Params>
class LazyEvaluation {
private:
// Function to be invoked later
T (*f)(Params...);
// Params for function f
Params... storedParams; // This line is not compilable!
bool evaluated;
T result;
public:
// Constructor remembers function pointer and parameters
LazyEvaluation(T (*f)(Params...),Params... params)
: f(f),
storedParams(params) //this line also cannot be compiled
{}
// Method which can be called later to evaluate stored function with stored arguments
operator T&() {
// if not evaluated then evaluate
if (! evaluated) {
result = f(storedParams...);
evaluated = true;
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我想至少让这个类类型的公共接口安全.虽然至少以某种方式获得这项工作更为重要.
我设法以某种方式保存可变数量的参数.但我无法将它们传递给函数f.我会把它写成答案,但我希望你在看到我丑陋的不工作尝试之前考虑一下你自己的解决方案.
我想用Microsoft Visual C++编译器2012年11月CTP(v120_CTP_Nov2012)编译上面的代码,但最好是存在独立于编译器的解决方案.
谢谢
这是我尝试解决它的方法:
参数包可以递归扩展并保存每个参数。函数存储应该可以做到这一点。它使用一个(重载两次)辅助函数。
template<typename T>
void storeHelperFunction(void*& memory, T last) {
*((T*)memory) = last;
memory = (void*)((char*)memory + sizeof(T));
}
template<typename T, typename... Params>
void storeHelperFunction(void*& memory, T first, Params... rest) {
storeHelperFunction(memory, first);
storeHelperFunction(memory, rest...);
}
template<typename... Params>
void store(void* memory, Params... args) {
// Copy of pointer to memory was done when passing it to this function
storeHelperFunction(memory, args...);
}
Run Code Online (Sandbox Code Playgroud)
函数存储需要一个指向内存的指针,其中应该保存可变数量的参数。
该指针可以指向一些动态分配的内存,或者更好地指向大小等于的结构sizeof...(Params)。这种具有任何所需大小的结构可以使用模板元编程来构造:
template <int N>
struct allocatorStruct {
char byte1;
allocatorStruct<N-1> next;
};
template <>
struct allocatorStruct<1> {};
Run Code Online (Sandbox Code Playgroud)
我不确定标准怎么说,也不知道除微软之外的其他编译器如何编译它。但是使用我的编译器,对于任何大于或等于 1 的 N,sizeof(allocatorStruct) 都等于 N。
因此allocatorStruct<sizeof...(Params)>与 Params 具有相同的大小。
创建与 Params 大小相同的内容的另一种方法是使用 type char [sizeof...(Params)]。这样做的缺点是,当您尝试将此类数组作为参数传递时,编译器仅传递指向该数组的指针。这就是为什么最好使用allocatorStruct<sizeof...(Params)>.
现在的主要思想是:
保存函数时,我们可以将其转换为:T (*)(allocatorStruct<sizeof...(Params)>)。保存函数的参数时,我们可以将它们保存到类型的结构体中allocatorStruct<sizeof...(Params)>。
参数的大小是相同的。尽管函数指针涉及函数的类型,但函数指向的函数将正确获取其数据。
至少我希望如此。根据调用约定,我预计传递的参数可能会重新排序或错误,因为从左到右保存参数和从右到左传递之间存在差异。但事实并非如此。使用 __cdecl 调用约定仅传递第一个参数,而另一个参数丢失。使用其他调用约定时,程序停止工作。
我没有花太多时间调试它并查找内存中的数据(在堆栈上)。这至少是正确的方法吗?