我正在编写一个围绕Lua的C Api的简单包装器,并且具有lua_State和amp;而不是指针。但是,当我尝试传递lua_State *值时,我必须取消引用它以通过引用传递。扩展为具有func sig的模板,其中vm按值传入,而不是引用。
由于可以在没有完整定义的情况下使用对象的引用和指针,有没有办法从指针值转换为只引用类型的前向声明的引用值?
编辑: 在玩了更多的代码之后。解除引用适用于其中一个函数调用,但在另一个函数调用中失败。
namespace Vm {
template<typename VM, typename T>
void push( VM vm, T value );
// If this function isn't here, push will fail too.
template<typename T>
void push( lua_State& luaState, T value ) {
Vm::push( luaState, value );
}
template<>
void push( lua_State& luaState, double value ) {
lua_pushnumber( &luaState, value );
}
template<typename VM>
void pop( VM vm, Uint32 nIndices );
template<>
void pop( lua_State& luaState, Uint32 nIndices ) {
lua_pop( &luaState, nIndices );
}
}
int main( int argc, char** argv )
{
lua_State* luaState = luaL_newstate();
luaL_openlibs( luaState );
Vm::push( *luaState, (double)1.2f ); // This works fine.
Vm::pop( *luaState, 1 ); // This generates error.
}
编译器错误:
error: invalid use of incomplete type ‘struct lua_State’
error: forward declaration of ‘struct lua_State’
error: initializing argument 1 of ‘void Vm::pop(VM, Uint32) [with VM = lua_State; Uint32 = unsigned int]’
答案 0 :(得分:1)
相关部分是5.3.1 [expr.unary.op]第1段:
一元*运算符执行间接:它所应用的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是一个左值,引用表达式指向的对象或函数。如果表达式的类型是“指向T的指针”,则结果的类型为“T”。[注意:可以取消引用指向不完整类型(cv void除外)的指针。由此获得的左值可以以有限的方式使用(例如,初始化参考);这个左值不能转换为prvalue,见4.1。 - 后注]
也就是说,您可以取消引用指向不完整类型的指针以获取对不完整类型的引用。您将无法对如此获得的参考文献做多少工作。基本上,你将无法做任何需要定义不完整类型的事情。
答案 1 :(得分:1)
使用引用时不需要完整的定义,但是你
当你实例化你的时候,也会有一些值传递的值
VM
为lua_State
的模板。值参数确实需要a
在呼叫站点完成声明以及定义函数的位置。
在您的代码中,Vm::push
专门用于lua_State&
和double
,
所以你得到Vm::push( *luaState, (double)1.2f );
的专业化
(但为什么(double)1.2f
,而不只是1.2
?),所以你得到了
专业化。 Vm::pop
没有专门化
但是,lua_State&
和int
,所以你得到了一个实例
模板,使用按值传递。 (我假设Uint32
是
不 int
的typedef。)
答案 2 :(得分:1)
更改Vm :: pop的定义以在VM参数上具有引用属性似乎可以解决问题:
namespace Vm {
template<typename VM>
void pop( VM& vm, Uint32 nIndices );
}
每次制作VM的副本都没有任何意义,除非你是一个顽固的功能程序员。我仍然不明白为什么调用解析为lua_State而不是lua_State&amp;,并在Vm :: push包装函数中正确推导出来(这个设法提供了更多的信息......某些方式..)。哦 - 好吧,它现在很好用。
感谢您的帮助!