1

我设法创建了一个库来帮助我向 SqlLite 库发出请求,特别是那些与 BLOB 文件相关的库。

问题来了,因为我觉得实现可以改进,但是我没有足够的知识来实现​​它。对这两个问题的任何帮助:

  1. 可以使用 SQL 语句作为 c-pure 字符串或 std::string 调用某些函数。他们俩最终都调用了相同的函数最终实现。如果我尝试删除函数声明和调用的“_”(请参阅​​源代码),则问题来自对模板函数的明确调用。我知道这是一个小问题,但我想知道是否有任何方法可以实现它。

  2. 我尝试对使用文件在数据库中加载 BLOB 的请求以及不使用 BLOBS 的请求使用相同的代码。区别在于第一个使用文件流作为参数,第二个没有任何流参数。SqlLite 强制调用特定函数来执行 sql 语句,因此我需要使用“if consexpr ...”条件子句将 0 个参数的情况与 1 个或多个流参数的情况分开。

源代码在前面介绍:

#include <string>
#include <sstream>
#include <utility>

class sqlite3 {};
class sqlite3_stmt {};
void sqlite3_step(sqlite3_stmt*) {}
sqlite3* db;

//Auxiliary BLOB functions
template<typename T>
bool sqlite3_blob(sqlite3_stmt*, const T& data, int col);

template<>
bool sqlite3_blob<std::ostringstream>(sqlite3_stmt* statement, const std::ostringstream& data, int col)
{
    //std::string buffer{ data.str() };
    return true;
}

//sqlite3 automatization request
template<typename... Args, std::size_t... Is>
constexpr bool sqlite3_request_(sqlite3* db, const char* sql, Args&&... args, std::index_sequence<Is...>)
{
    sqlite3_stmt* statement{};
    (sqlite3_blob(statement, std::forward<Args>(args), Is + 1), ...);

    if constexpr (sizeof...(Args) == 0) sqlite3_step(statement);//Horrible conditional statement. Is there any way of getting rid of it???

    return true;
}

template<typename... Args>
constexpr bool sqlite3_request(sqlite3* db, const char* sql, Args&&... args)
{
    return sqlite3_request_<Args...>(db, sql, std::forward<Args>(args)..., std::make_index_sequence<sizeof...(Args)>{});//Need to change the name because calling function is not able to unambiguosly called the right on
}

//For std::string arguments:
 template<typename... Args>
constexpr bool sqlite3_request(sqlite3* db, const std::string& sql, Args&&... args)//args contain loading data for blobs, if any
{
    return sqlite3_request_<Args...>(db, sql.c_str(), std::forward<Args>(args)..., std::make_index_sequence<sizeof...(Args)>{});// Possible to improve? Unambiguos calling to function if '_' eliminated in function calling and declaration
}

int main()
{
    const std::ostringstream data;
    std::string sql = "INSERT INTO scenarios(file) VALUES(?);";//file is a BLOB field
    sqlite3_request(db, sql, data);
}

请注意,我已经清理并模拟了所有 SqlLite 函数。这不是关于 SqlLite 的问题,而是关于改进模板样式的问题。

此外,这是一个指向http://coliru.stacked-crooked.com/a/ec8e8bf65f451b20所述源代码的 coliru 链接。

4

1 回答 1

1

有一些方法可以提供帮助。对于第一个问题,您可以使用命名空间来修复模棱两可的调用。关于第二个问题,如果不想使用if constexpr,也可以定义nullptr_t为参数类型,然后调用nullptr。这可能不符合您的大部分期望,但希望您对此感到满意

#include <string>
#include <sstream>
#include <utility>

class sqlite3 {};
class sqlite3_stmt {};
sqlite3* db;

void sqlite3_blob(sqlite3_stmt*,std::nullptr_t, int) {}

//Auxiliary BLOB functions
template<typename T>
bool sqlite3_blob(sqlite3_stmt*, const T& data, int col);

template<>
bool sqlite3_blob<std::ostringstream>(sqlite3_stmt* statement, const std::ostringstream& data, int col)
{
    //std::string buffer{ data.str() };
    return true;
}
namespace details {
//sqlite3 automatization request
template<typename... Args, std::size_t... Is>
constexpr bool sqlite3_request(sqlite3* db, const char* sql, Args&&... args, std::index_sequence<Is...>)
{
    sqlite3_stmt* statement{};
    (sqlite3_blob(statement, std::forward<Args>(args), Is + 1), ...);

    return true;
}
}

template<typename... Args>
constexpr bool sqlite3_request(sqlite3* db, const char* sql, Args&&... args)
{
    return details::sqlite3_request<Args...>(db, sql, std::forward<Args>(args)..., std::make_index_sequence<sizeof...(Args)>{});//Need to change the name because calling function is not able to unambiguosly called the right on
}

//For std::string arguments:
 template<typename... Args>
constexpr bool sqlite3_request(sqlite3* db, const std::string& sql, Args&&... args)//args contain loading data for blobs, if any
{
    return details::sqlite3_request<Args...>(db, sql.c_str(), std::forward<Args>(args)..., std::make_index_sequence<sizeof...(Args)>{});// Possible to improve? Unambiguos calling to function if '_' eliminated in function calling and declaration
}

int main()
{
    const std::ostringstream data;
    std::string sql = "INSERT INTO scenarios(file) VALUES(?);";//file is a BLOB field
    sqlite3_request(db, sql, data);
    sqlite3_request(db, sql, nullptr);
}
于 2021-06-22T06:10:50.727 回答