问题描述
我设法创建了一个库来帮助我向 sqlLite 库发出请求,特别是那些与 BLOB 文件相关的请求。
问题来了是因为我觉得实现可以改进,但我没有足够的知识来实现它。对这两个问题的任何帮助:
-
可以使用 sql 语句作为 c-pure 字符串或 std::string 调用某些函数。他们两个最终调用同一个函数最终实现。如果我尝试删除函数声明和调用的“_”(请参阅源代码),则问题来自对模板函数的明确调用。我知道这是一个小问题,但我想知道是否有任何方法可以实现它。
-
我尝试对使用文件在数据库中加载 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,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::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,data);
}
请注意我已经清理并模拟了所有 sqlLite 函数。这不是关于 sqlLite 的问题,而是关于改进模板样式的问题。
此外,这里是指向所述源代码的coliru链接http://coliru.stacked-crooked.com/a/ec8e8bf65f451b20
。
解决方法
有一些方法可以提供帮助。对于第一个问题,您可以使用命名空间来修复不明确的调用。关于第二个问题,如果不想使用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,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::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,data);
sqlite3_request(db,nullptr);
}