传递Reference时模板扩展失败?

时间:2013-09-23 17:47:05

标签: c++ templates lua

我正在编写一个围绕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]’

3 个答案:

答案 0 :(得分:1)

相关部分是5.3.1 [expr.unary.op]第1段:

  

一元*运算符执行间接:它所应用的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是一个左值,引用表达式指向的对象或函数。如果表达式的类型是“指向T的指针”,则结果的类型为“T”。[注意:可以取消引用指向不完整类型(cv void除外)的指针。由此获得的左值可以以有限的方式使用(例如,初始化参考);这个左值不能转换为prvalue,见4.1。 - 后注]

也就是说,您可以取消引用指向不完整类型的指针以获取对不完整类型的引用。您将无法对如此获得的参考文献做多少工作。基本上,你将无法做任何需要定义不完整类型的事情。

答案 1 :(得分:1)

使用引用时不需要完整的定义,但是你 当你实例化你的时候,也会有一些值传递的值 VMlua_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包装函数中正确推导出来(这个设法提供了更多的信息.​​.....某些方式..)。哦 - 好吧,它现在很好用。

感谢您的帮助!