0

我正在做一些关于 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 (? , ?)" ,

并创建一些绑定变量,这些变量引用客户端变量的地址,如 kk、jj。

我的问题是:

由于 operator%() 的优先级高于 operator,() ,jj 坚持使用 ")" % 并且编译错误抱怨类 Small 没有 operator%。

怎么做 ?让 char*、kk、jj 和 char* 通过写命令进入 sql 对象。

4

3 回答 3

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;
}
于 2013-07-19T06:57:56.090 回答
0

怎么做?

你不能。无法更改 C++ 运算符的优先顺序。

即使可以,这也可能是个坏主意。像这样重载随机运算符被认为是不好的做法。

我建议坚持 C++ 约定,并<<在任何地方使用(因为我不清楚为什么需要多个不同的运算符)。

但是,尚不清楚为什么在这里需要运算符重载。对我来说,这段代码写起来会更清晰:

sql = bind("insert into test_table (tiny_col,short_col) values (?,?)", kk, jj);
于 2013-07-19T03:48:02.517 回答
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 个错误,您能找出它们吗?num of ? 不等于 num of 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"

现在它更具可读性和清晰性。

于 2013-07-19T14:06:00.437 回答