1

std::cout とファイルにログを記録するロガーを作成しようとしています。これは私のクラスです:

.h ファイル:

class ProblemsManager {
        (...)
private:
        (...)

    class logger {
    private: 
        std::ofstream fileStream;
        static const std::string LOG_PATH;
    public: 
        logger();
        ~logger();


    template<class T> 
    friend logger & operator<<(logger &log, const T & bytes) {
        log.fileStream<<bytes;
        std::cout<<bytes;
        return log;
    }
    };
};

.cpp ファイル

(...)
const std::string ProblemsManager::logger::LOG_PATH = "F:\\Dropbox\\workspace - Visual Studio\\PEuler\\PEuler\\PEuler.log";

ProblemsManager::logger::logger() : fileStream(LOG_PATH,std::ofstream::out) {}
ProblemsManager::logger::~logger() {}

次に、私がやろうとすると:

ProblemsManager::logger log;
log<<"test";

私は得る:

1>f:\dropbox\workspace - visual studio\peuler\peuler\problemsmanager.cpp(47): エラー C3767: '<<': 候補関数にアクセスできません 1> 'f:\ のフレンド関数である可能性がありますdropbox\workspace - visual studio\peuler\peuler\problemsmanager.h(37)' : '<<' [引数依存の検索で見つかる場合があります]

4

3 に答える 3

3

テンプレートにはいくつかの問題があります。1 つ目は、どちらも参照のみが異なり、問題が発生することです。必要なのは1つだけです(引数を読み取り、書き込みません):

    template<class T> 
    friend logger & operator<<(logger& log, const T & bytes);
    //                                      ^^^^^

2 つ目の問題は、インスタンス化の生成時にコンパイラがテンプレートを認識できる場所にテンプレートを定義する必要があることです。これは基本的に、定義が .cpp ファイルではなくヘッダーにある必要があることを意味します。[*]

さらに、logger型は に対してプライベートProblemsManagerであるため、名前空間レベルからアクセスすることはできません。ネストされた型にアクセスできないため、free 関数を定義する際に問題が発生します。オプションは、型を public にするか、関数を のフレンドにするProblemsManagerか、または私が推奨するように、クラス定義内でテンプレートをインラインで定義することです。

class ProblemsManager {
private:
    class logger {
        template<class T> 
        friend logger & operator<<(logger& log, T & bytes) {
           // implementation goes here
        } 
    };
};

[*]loggerこれは実際にはルールの例外である可能性があります。プライベート タイプであるため、すべての の使用と がメンバーoperator<<を定義する翻訳単位内で発生すると想定することしかできません。ProblemsManagerその場合は、この段落を無視してかまいません。

于 2013-08-01T21:21:32.450 に答える
0

じっくりやってみます。

log<<"test";

上記の呼び出しは、最初のパラメーター logger & と 2 番目の const char[5] を使用した operator<< 関数の呼び出しです。

最初のオーバーロードは、参照をオーバーロードして const オブジェクトを渡すため、おそらくバインドできません。配列を値で渡しているため、2番目は失敗し、それを行うことはできません。配列がポインターに折りたたまれない理由がわかりません。

const 参照でオーバーロードしようとしましたか? ところで、なぜ値と参照をオーバーロードするのですか?

于 2013-08-01T21:24:32.617 に答える
0

operator<< 関数はメンバーではなくフレンドであるため、内部で「this」を使用することはできません。そこに 'log' を返し、ログ メンバーを 'log.' で適切に修飾することをお勧めします。

于 2013-08-01T21:03:21.903 に答える