C++関数のリロード時に戻り値のタイプにもリロード決議を加えるにはどうすればいいですか?


周知のように、C++関数のリロード時の戻り値は、リロード決定に関与しません.つまり、
int lex_cast(const char*);
double lex_cast(const char*);
このような2つの関数が同じコンパイルユニットの同じ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_キャストはこの一時変数をメンバーに保存したが、ここで成功したのは間違いない.解放されたc_のためだ.str()そのメモリはちょうど再割り当てされていないので、危険です.
実際には、これは問題ありません.C++の標準は、一時変数の生存期間は、真のサブ式ではなく、その式(全体)を含むことを規定しています.この言葉をよく味わいましょう.
上はただmy_cast非テンプレートの場合my_castにはテンプレートパラメータが含まれ、my_キャストメンバーもテンプレートでなければなりませんが、どうすればいいですか?
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_を使っていませんキャスト、亀速をコンパイルする問題はありません.(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);
}