怎样让C++函数重载时连返回值类型也加入重载决议?

来源:互联网 发布:淘宝代购兼职 编辑:程序博客网 时间:2024/04/27 23:29

众所周知,C++函数重载时返回值是不参与重载决议的, 也就是说:

int lex_cast(const char*);

double lex_cast(const char*);

这样两个函数在同一个编译单元同一个 namespace 中时, 会编译报错.

怎么办呢?

一个小技巧:

#include <iostream>#include <string>#include <boost/lexical_cast.hpp>class my_cast {    const char* s;public:    template<class Target>    operator Target() const {        return boost::lexical_cast<Target>(s);    }    my_cast(const char* s) : s(s) {}};int main() {    using namespace std;    long long ll = my_cast("12345678910111213");    int ii = my_cast("-123");    string ss = my_cast("abcde");    double dd = my_cast(('3' + string(".2222")).c_str());    cout << ll << endl;    cout << ii << endl;    cout << ss << endl;    cout << dd << endl;    return 0;}

小得几乎不值一提. 但是, 这段代码中, 可能有些仔细的人会提出疑问:

('3' + string(".2222")).c_str()

这里返回的 const char* 是属于临时变量的, 而 my_cast 竟然把这个临时变量保存到它的成员, 这里能成功并无错应该只是因为被释放的 c_str() 那块内存恰好未被重新分配, 太危险了!

其实, 这没任何问题, C++ 标准规定: 临时变量的生存期是包含它的那个表达式(整个), 而非任何一个真子表达式. 仔细体味这句话吧!

上面只是在 my_cast 非模板的情况, 如果 my_cast 包含模板参数, 并且 my_cast 成员也必须是模板, 怎么办?

template<class Source>class my_cast_imp {    Source s;public:    template<class Target>    operator Target() const {        return boost::lexical_cast<Target>(s);    }    my_cast_imp(const Source& s) : s(s) {}};template<class Source>my_cast_imp<Source> my_cast2(const Source& s) {    return my_cast_imp<Source>(s);}

只需定义一个辅助模板类, 再加一个模板函数去实例化模板类.

核心思想只有一个: 使用  operator class conversion, 下面是一个比较实用的 cast, 没有用 boost::lexical_cast, 没有编译龟速的问题. (boost 过度使用 template 了)

#include <stdlib.h>#include <string>class goldcast_imp {    const char* s;    int base;public:    goldcast_imp(const char* s, int base)        : s(s), base(base)    {}    operator int     () const  { return (int)     strtol (s, NULL, base); }    operator unsigned() const  { return (unsigned)strtoul(s, NULL, base); }    operator   signed long     () const { return strtol  (s, NULL, base); }    operator   signed long long() const { return strtoll (s, NULL, base); }    operator unsigned long     () const { return strtoul (s, NULL, base); }    operator unsigned long long() const { return strtoull(s, NULL, base); }    operator float()  const { return strtof(s, NULL); }    operator double() const { return strtod(s, NULL); }    operator long double() const { return strtold(s, NULL); }    operator std::string() const { return std::string(s); }};goldcast_imp goldcast(const std::string& s, int base = 10) {    return goldcast_imp(s.c_str(), base);}goldcast_imp goldcast(const char* s, int base = 10) {    return goldcast_imp(s, base);}

原创粉丝点击