当传递引用时,模板扩展失败?

我正在编写一个简单的 Lua C Api 包装器,并让函数接受 lua_State& 而不是指针。然而,当我尝试传递一个 lua_State* 值时,我必须解引用它才能通过引用传递。模板的扩展形式中,func sig 传递的是值而不是引用。

由于可以在不完全定义对象的情况下使用对象的引用和指针,是否有一种方式可以只使用类型的前向声明将指针值转换为引用值?

编辑:在更多的代码中进行调试之后,解引用可以在一个函数调用中正常工作,但在另一个函数调用中失败。

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]’
点赞
用户1120273
用户1120273

相关章节是5.3.1 [expr.unary.op] 第1段:

一元运算符 * 执行间接寻址:它应用于的表达式应为对象类型的指针或函数类型的指针,结果为一个左值,指向表达式所指向的对象或函数。如果表达式类型为“指向 T 的指针”,结果的类型为“T”。[注意:可以对不完整类型(除 cv void 外)的指针执行解引用操作。因此得到的左值只能以有限的方式使用(例如用于初始化引用);这个左值不得转换为 prvalue,请参见4.1。--末尾注释]

也就是说,可以对不完整类型的指针执行解引用操作,以获得不完整类型的引用。但你不能用这个引用做太多事情。基本上,你不能执行需要不完整类型定义的任何操作。

2013-09-23 18:25:21
用户649665
用户649665

在使用引用的情况下,没有必要进行完整的定义,但是当你使用 VM 作为 lua_State 实例化你的模板时,你也有一些传值参数。而值参数需要在调用站点和函数定义处进行完整声明。

在你的代码中,Vm::push 针对 lua_State&double 进行了特化,因此你得到了 Vm::push( *luaState, (double)1.2f ); 的特化版本(但为什么是 (double)1.2f,而不是 1.2?),所以你得到了这个特化版本。然而,Vm::pop 没有针对 lua_State&int 进行特化,因此你会得到模板的实例化,这将使用传值方式。(我假设 Uint32 不是 int 的 typedef。)

2013-09-23 18:32:51
用户1884312
用户1884312

将 Vm::pop 的定义更改为在 VM 参数上具有引用属性似乎可以解决问题:

namespace Vm {
template<typename VM>
    void pop( VM& vm, Uint32 nIndices );
}

每次都复制 VM 没有什么意义,除非你是一个死忠的函数式编程者。我仍然不明白为什么调用会解析为 lua_State 而不是 lua_State&,并且在 Vm::push 的包装函数中适当地推导出(这个函数成功地提供了更多信息...不知怎么搞的)。 哦,好了,现在工作得很好。

感谢你的帮助!

2013-09-23 23:53:32