我正在做一些关于mysql C API封装的练习。 当我决定写这样的SQL时。
template<class T> C_SQL& operator%(const char* txt)...;
template<class T> C_SQL& operator%(T& t)...;
template<class T> C_SQL& operator,(T& t)...;
Int kk;
Small jj;
C_SQL sql;
sql % "insert into test_table (tiny_col,short_col) values (" % kk , jj % ")" ;
我的计划是通过重载三个运算符,我可以得到这样的SQL文本:
"insert into test_table (tiny_col,short_col) values (? , ?)" ,
并创建一些绑定变量,这些变量引用客户端var的地址,如kk,jj。
我的问题是:
由于运算符%()的prioity高于运算符,(),jj坚持“)”% 并且complie错误抱怨类Small没有运算符%。
怎么办?让char *,kk,jj和char *通过编写命令进入sql对象。
答案 0 :(得分:0)
怎么办?
你做不到。无法更改C ++运算符的优先顺序。
即使你可以,这可能是一个坏主意。像这样重载随机运算符被认为是不好的做法。
我建议坚持使用C ++约定,并在任何地方使用<<
(因为我不清楚为什么你需要多个不同的运算符)。
然而,目前尚不清楚为什么你需要操作员重载。对我来说,这段代码将更清晰地写成:
sql = bind("insert into test_table (tiny_col,short_col) values (?,?)", kk, jj);
答案 1 :(得分:0)
#include <iostream>
#include <string>
#include <boost/tuple/tuple.hpp>
class C_SQL
{
public:
C_SQL& operator%(const char* txt){
text_ += txt;
return *this;
}
template <typename Tuple>
C_SQL& operator%( const Tuple& t )
{
text_+="values(" ;
return bind_tuple_helper<Tuple,boost::tuples::length<Tuple>::value>::bind( *this, t );
}
private:
template <typename Tuple, size_t size>
struct bind_tuple_helper {
static C_SQL& bind( C_SQL& s, const Tuple& t ) {
//text appends
s.text_+='?' ;
//deal with a variable , this is a test
std::cout<< boost::get<boost::tuples::length<Tuple>::value - size>(t) << std::endl;
//text appends
if (size != 1){
s.text_+=',' ;
}
//another var
return bind_tuple_helper<Tuple,size-1>::bind( s, t );
}
};
//terminator
template <typename Tuple>
struct bind_tuple_helper<Tuple,0> {
static C_SQL& bind( C_SQL& s, const Tuple& t ) {
s.text_ += ')';
return s;
}
};
std::string text_;
};
int main() {
#define values boost::make_tuple
int kk=1;
double jj=2;
long ll=3;
C_SQL sql;
sql % "insert int test_tbl (col1,col2,col3) " % values(kk,jj,ll) ;
return 0;
}
答案 2 :(得分:0)
我完成了我的工作。现在我会解释为什么我不喜欢问号。
bind("select t1.c1,t1.c2 from t1,t2,t3 "
"where t1.c1=? and t1.c4 between ? and ?"
"t1.c1=t2.c1 and t2.c4=t3.c3 and t2.c3>?" , tt,hh,jj,aa,,rr);
bind("insert into t4 values(?,?,?,?,?,?,?,?,?,?,?,?)", kk,tt,aa,vv,cc,ee,zz,jj,oo);
它更具C风格,容易出错,你必须有一个良好的视力 (它们中有2个错误,你能找到它们吗? 数量?不等于提供的var的数量)
我选择了更多的C ++风格。
template<class T0,class T1,class T2,class T3>
tuple<T0,T1,T2,T3> values(T0& t0,T1& t1,T2& t2,T3& t3)
{
using namespace boost;
return make_tuple(ref(t0),ref(t1),ref(t2),ref(t3));
}
class Small{...};
class Tiny {...};
class String{...};
class Datetime{...};
Small kk;
char buff[32];
String ss(buff,32); //Wrapper. like boost::asio::array
double dd; //primitive C++ type. does not support NULL field
Double bb; //Wrapper type. support NULL semantics
C_SQL sql;
sql % "insert int test_tbl (c1,c2,c3,c4)" % values(kk,ss,dd,bb) ;
C_SQL sql2;
sql2 % "select * from t1,t2 where t1.c1=" %kk%
"and t1.c2 between" %bb% " and " %dd%
"and t2.c2 = t1.c5"
现在它更加简洁明了。