【发布时间】:2015-05-30 22:07:25
【问题描述】:
我正在尝试编写一些代码,将 C++ 函数包装成 Lua 可以使用的东西。我试图解决的主要问题之一是将 Lua 堆栈中弹出的值传递给 C++ 函数的参数。对我有用的天真的方法是:
template<typename Ret, typename... Args>
int luaDRCall(lua_State* s) {
typedef RDelegate<Ret, Args...>* FunctionPtr;
FunctionPtr f = (FunctionPtr)popUpvalueObject(s);
Ret retValue = f->invoke(popValue<Args>(h)...);
return ScriptValueSender<Ret>::push(h, retValue);
}
但是,这给我带来了问题,因为“popValue(h)...”不能保证从右到左执行。在 MSVC 的“调试”版本下,它工作正常......但“发布”版本以相反的顺序调用函数。因此,我编写了一些保证以正确顺序弹出值的代码:
template<typename Ret, typename... Args>
int luaDRCall(lua_State* s) {
void* del = popUpvalueObject(s);
return fRCall<Ret, Args...>(s, del);
}
template<typename Ret, typename Arg, typename... Args>
int fRCall(EnvironmentHandle h, void* del) {
Arg v = popValue<Arg>(h);
return fRCall<Ret, Args..., Arg>(h, del, v);
}
template<typename Ret, typename Arg, typename... Args, typename... Popped>
int fRCall(EnvironmentHandle h, void* del, Popped... vPopped) {
Arg v = popValue<Arg>(h);
return fRCall<Ret, Args..., Popped..., Arg>(h, del, vPopped..., v);
}
template<typename Ret, typename... Args>
int fRCall(EnvironmentHandle h, void* del, Args... vPopped) {
typedef RDelegate<Ret, Args...>* FunctionPtr;
FunctionPtr f = (FunctionPtr)del;
Ret retValue = f->invoke(vPopped...);
return ScriptValueSender<Ret>::push(h, retValue);
}
现在,尝试编译此代码会导致:
2>c:\induztry\git\vorb\include\script\Script.h(66): fatal error C1060: compiler is out of heap space
2>c1xx : fatal error C1063: INTERNAL COMPILER ERROR
2> Please choose the Technical Support command on the Visual C++
2> Help menu, or open the Technical Support help file for more information
有人知道什么是错的,我该如何解决?对此问题的任何其他解决方案也将不胜感激。谢谢。
编辑 1: 在以下答案之一的帮助下,我已将我的代码更改为以下代码,只要该函数至少有一个参数,它现在就可以正常工作。如果没有参数存在,我有编译器错误:
template<size_t... Is>
struct index_sequence {};
template<size_t N, size_t... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};
template<size_t... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
template<typename... T>
struct index_sequence_for : make_index_sequence<sizeof...(T)> {};
template <typename Ret, typename F, typename Tuple, size_t... Is>
Ret invoke(F f, Tuple& t, index_sequence<Is...>) {
return f->invoke(std::get<Is>(t)...);
}
template<typename Ret, typename... Args>
int luaDRCall(EnvironmentHandle h) {
typedef RDelegate<Ret, Args...>* FunctionPtr;
FunctionPtr f = (FunctionPtr)popUpvalueObject(h);
std::tuple<Args...> tValue { popValue<Args>(h)... };
Ret retValue = invoke<Ret>(f, tValue, index_sequence_for<Args...>());
return ScriptValueSender<Ret>::push(h, retValue);
}
我有必要将这一切都放在一个函数中使用,并且尝试对没有参数进行模板特化会导致编译器错误。
1>c:\induztry\git\vorb\include\script\Script.h(68): error C2143: syntax error : missing '}' before '<fake-type>'
1> c:\induztry\git\vorb\include\script\Script.h(105) : see reference to function template instantiation 'i32 vorb::script::impl::fRCall<Ret,>(vorb::script::EnvironmentHandle,void *)' being compiled
1> with
1> [
1> Ret=int
1> ]
1> c:\induztry\git\vorb\include\script\Script.h(122) : see reference to function template instantiation 'int vorb::script::impl::luaDRCall<Ret,>(lua_State *)' being compiled
1> with
1> [
1> Ret=int
1> ]
1> C:\InduZtry\Git\Vorb\include/script/Environment.h(76) : see reference to function template instantiation 'vorb::script::ScriptFunc vorb::script::fromRDelegate<Ret,>(void)' being compiled
1> with
1> [
1> Ret=int
1> ]
1> VorbScript.cpp(101) : see reference to function template instantiation 'void vorb::script::Environment::addCRDelegate<int,>(const std::string &,RDelegate<int,> &)' being compiled
1>c:\induztry\git\vorb\include\script\Script.h(68): error C2143: syntax error : missing ';' before '<fake-type>'
1>c:\induztry\git\vorb\include\script\Script.h(69): error C2146: syntax error : missing ';' before identifier 'retValue'
1>c:\induztry\git\vorb\include\script\Script.h(69): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\induztry\git\vorb\include\script\Script.h(69): error C2065: 'f' : undeclared identifier
1>c:\induztry\git\vorb\include\script\Script.h(69): error C2065: 'tValue' : undeclared identifier
1>c:\induztry\git\vorb\include\script\Script.h(69): error C3546: '...' : there are no parameter packs available to expand
1>c:\induztry\git\vorb\include\script\Script.h(69): error C2065: 'Args' : undeclared identifier
1>c:\induztry\git\vorb\include\script\Script.h(69): error C3544: 'T': parameter pack expects a type template argument
1>c:\induztry\git\vorb\include\script\Script.h(69): error C2955: 'vorb::script::impl::index_sequence_for' : use of class template requires template argument list
1> c:\induztry\git\vorb\include\script\Script.h(58) : see declaration of 'vorb::script::impl::index_sequence_for'
1>c:\induztry\git\vorb\include\script\Script.h(70): error C2059: syntax error : 'return'
1>c:\induztry\git\vorb\include\script\Script.h(70): error C2923: 'vorb::script::ScriptValueSender' : 'vorb::script::impl::Ret' is not a valid template type argument for parameter 'T'
1> c:\induztry\git\vorb\include\script\Script.h(69) : see declaration of 'vorb::script::impl::Ret'
1>c:\induztry\git\vorb\include\script\Script.h(70): error C2955: 'vorb::script::ScriptValueSender' : use of class template requires template argument list
1> c:\induztry\git\vorb\include\script\ScriptValueSenders.h(36) : see declaration of 'vorb::script::ScriptValueSender'
1>c:\induztry\git\vorb\include\script\Script.h(70): error C2027: use of undefined type 'vorb::script::ScriptValueSender'
1> c:\induztry\git\vorb\include\script\ScriptValueSenders.h(36) : see declaration of 'vorb::script::ScriptValueSender'
1>c:\induztry\git\vorb\include\script\Script.h(71): error C2059: syntax error : '}'
1>c:\induztry\git\vorb\include\script\Script.h(71): error C2143: syntax error : missing ';' before '}'
1>c:\induztry\git\vorb\include\script\ScriptImpl.h(82): error C2143: syntax error : missing ';' before '{'
1>c:\induztry\git\vorb\include\script\ScriptImpl.h(82): error C2447: '{' : missing function header (old-style formal list?)
【问题讨论】:
-
内部编译器错误始终是编译器错误。您能做的最好的事情就是找到一种解决方法,为您提供所需的行为;我在那里没有任何建议,但这不一定是你的问题(我没有足够详细地阅读一堆代码)。
-
我可以发誓总是保证按正确的顺序打开包装...
-
@MooingDuck 我认为问题出在解包函数的未指定执行顺序。见stackoverflow.com/a/833929/234175。所以假设,编译器可以先执行中间的解包函数,然后是最后一个,最后是第一个。按该顺序弹出内容显然会导致 lua 堆栈出现问题。
-
@DarthZaloj 该内部错误表明 MSVC 中可能存在失控的模板实例化。您是否尝试过使用 mingw 或 clang 构建它?
-
@greatwolf:该链接是关于通用函数参数的。我很确定可变参数模板参数解包有特殊规则。我会看看我能找到什么。
标签: c++ templates c++11 lua stack