C++:使用模板折叠具有不同类型和功能的重复代码

标签 c++ templates

我正在编写一个允许 Lua 以不同类型和字节顺序在内存块中读取和写入任意字节的库。我使用 C++ 模板在某种程度上避免了重复,但我没能完全避免它:

/* Read one or more sequential values from the blob and push to the Lua stack
 * using lua_pushinteger().
 * Lua: the Lua state to push to.
 * offset: The byte offset to read from.
 * count: The number of values to read.
 * This method is called from Blob::read() which is called from Lua methods.
 * For offsets outside the valid range, it returns nil.
 */
template <typename T>
lua_Integer Blob::readi(lua_State *Lua, lua_Integer offset, lua_Integer count) {
    if(offset < 0) offset += this->size;
    else offset--; //make 0-based

    for(int i=0; i<count; i++) {
        if(offset >= 0 && offset < this->size) {
            T value = *(&this->data[offset + this->pageOffset]);
            lua_pushinteger(Lua, value);
            offset += sizeof(T);
        }
        else lua_pushnil(Lua);
    }
    return count;
}

/* Same as readi but uses lua_pushnumber
 * even with templates we end up duplicating logic :|
 */
template <typename T>
lua_Integer Blob::readf(lua_State *Lua, lua_Integer offset, lua_Integer count) {
    if(offset < 0) offset += this->size;
    else offset--; //make 0-based

    for(int i=0; i<count; i++) {
        if(offset >= 0 && offset < this->size) {
            T value = *(&this->data[offset + this->pageOffset]);
            lua_pushnumber(Lua, value);
            offset += sizeof(T);
        }
        else lua_pushnil(Lua);
    }
    return count;
}

当我们想要读取floatdouble 值时,我们必须使用lua_pushnumber(lua_State *Lua, lua_Number num) 而不是lua_pushinteger(lua_State *Lua, lua_Integer num). (通常 lua_Integer 是一些整数类型的 typedef,例如 int32_t,而 lua_Numberdouble 的 typedef。 ) 所以我不知道如何避免使用模板重复这个函数,因为 lua_pushintegerlua_pushnumber 接受不同的类型。

此外,我想添加对指定字节顺序的支持(使用 endian.h 中的函数):您可以指定正在读取的值假定为大端顺序,小端, 或 native (以主机为准)。同样,我不知道如何使用模板实现这一点,因为字节顺序函数处理不同的类型。

最佳答案

void lua_push_anything( lua_State* s, lua_Integer i ) {
  lua_push_integer( s, i );
}
void lua_push_anything( lua_State* s, lua_Number i ) {
  lua_push_number( s, i );
}
void lua_push_anything( lua_State* s, bool b ) {
  lua_push_boolean( s, b ); // actually takes an `int`.
}
void lua_push_anything( lua_State* s, std::string s ) {
  lua_pushlstring( lua_State* s, s.c_str(), s.size() );
}

这解决了类型问题——您有一个单独的重写,可以分派(dispatch)到正确的 extern "C" lua_* 函数。

如果需要,您可以用类似的方式处理字节顺序。

关于C++:使用模板折叠具有不同类型和功能的重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25050293/

相关文章:

email - MAGENTO 我在哪里可以找到 magento 中的所有发票和订单模板?

c++ - 使用 C++ 开发一个 Facebook 应用程序

用于在编译时确定成员数量的 C++ 宏/元程序

c++ - 如何为 sfml 2.0 安装 libGLEW 1.5?

c++ - 嵌套模板类的模板类模板参数特化

c++ - 带有模板参数的 std::function

C++ template double std::complex<double> 范数和积

ruby-on-rails - 在助手中渲染 content_for block

c++ - C 和 C++ 库错误

c# - 如何在 C# 中执行哨兵模式?