解决C++函数模板重载时出现的歧义,函数模板隐藏技术

函数重载是C++中实现静态多态的重要机制,在定义函数重载时,特别是在有函数模板加入时,更需要小心定义参数,防止歧义的出现


举例来说,有下面两个重载函数,用于执行数据库查询并返回查询结果,分别对应到查单个值和查列表两个版本,模板类型参数V是查询结果的类型:

template<class V>

long query(const std::string &strSql, V *pv, CDBConn *poConn=NULL);


template<class V>

long query(const std::string &strSql, long *plLen, V *pv, CDBConn *poConn=NULL);


实际以long类型调用第一个重载版本函数时:

    CDBConn *pcon = NULL;
    long lValue = 0;
    query("select count(*) from tbl_data", &lValue, pcon);


编译器会提示歧义:

1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>Compiling...
1>test.cpp
1>e:\cj\boost_test\test\test.cpp(321) : error C2668: 'query' : ambiguous call to overloaded function
1>        e:\cj\boost_test\test\test.cpp(314): could be 'long query<CDBConn>(const std::string &,long *,V *,CDBConn *)'
1>        with
1>        [
1>            V=CDBConn
1>        ]
1>        e:\cj\boost_test\test\test.cpp(310): or       'long query<long>(const std::string &,V *,CDBConn *)'
1>        with
1>        [
1>            V=long
1>        ]
1>        while trying to match the argument list '(const char [1], long *, CDBConn *)'
1>Build log was saved at "file://e:\cj\boost_test\test\Debug\BuildLog.htm"
1>test - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

编译错误提示表示两个版本都能满足参数类型的匹配,即:

如果选择第一个版本,V的类型就被推导为long类型;而如果选择第二个版本,V的类型被推导为CDBConn类型,由于最后一个连接参数有缺省值可以不填


看来只需要将第二个重载版本的最后一个参数的缺省值去掉,不提供缺省值就可以解决这个问题了。

那有没有鱼和熊掌兼得的方法呢?


让第二个函数模板在V被推导成CDBConn时,不让自己生效不就行了!

这就是本文重点要介绍的函数模板隐藏技术了^^


原理:如果一个函数模板不能成功推导自己的所有模板参数,编译器就不会让它参与重载

提示:通过在函数的返回值类型上下工夫,就可以不修改函数参数的原型来达到我们的目的了。

到这里大家可以自己先想想实现方案,实现代码稍后附上^^


-------------------------------------------------------------------------------











实现代码:


按如下代码修改第二个重载版本的返回值类型:

template<class V>  typename enable_if_not_conn_type<V>::type
query(const std::string &strSql, long *plLen, V *pv, CDBConn *poConn=NULL);


上面模板enable_if_not_conn_type对类型CDBConn的特化版本无法推导出type类型:

template <class T>
struct enable_if_not_conn_type
{
    typedef long type;
};
template <>
struct enable_if_not_conn_type<CDBConn>  //特化版本没有定义type类型
{
};


更通用的模板定义如下:

template <class T1, class T2>
struct enable_if_not_type
{
    typedef long type;
};

template <class T>
struct enable_if_not_type<T,T>
{
};


使用上面模板,重新定义函数:

template<class V>  typename enable_if_not_type<V,CDBConn>::type
query(const std::string &strSql, long *plLen, V *pv, CDBConn *poConn=NULL);


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值