1

現在、2 つのストリームのラッパーを作成しています。最後に、との会話を真似しPersonて、コードを明確にし、使いやすくしたいと思います。

宣言

class Person
{
public:
    void process();

private:
    std::stringstream _request;
    std::stringstream _response;
}

使用法

Person daniel;
std::stringstream answer;
daniel << "Hello" << std::endl; // f.e std::endl means end of the phrase
daniel << "How" << "are you";
daniel << "doing?";
daniel >> answer;
daniel.process();
std::cout << "Daniel says: " << answer;
// or
std::cout << "Daniel says: " << daniel;

<<オーバーロードと演算子で達成できる気がしますが>>、行き詰まっています。これらの目的でストリームを使用したことはありません。私はたくさんグーグルで検索しましたが、明らかに基本的なことをまだ理解できていません。

一言で言えば

std::ostream& operator<<(std::ostream& o, const person& p)
{
    output << p._response.rdbuf();

    return (output);
}

std::istream& operator>>(std::istream& i, person& p)
{
    p._request << i.rdbuf();
    // internal process() call probably will be better
    return (p._request);
}

いくつかの例は確かに素晴らしいものですが、行き詰まりから私を駆り立てるラフなアイデアに絶対に満足しています.

4

2 に答える 2

2

正直なところ、なぜこれが必要なのかわかりませんが、これはある種の演習または宿題だと思います。とにかく、この機能の実装に関連する微妙な点がいくつかありますが、それを自分で理解することはできないと思われるので、ここに実際の解決策を示します。

#include <iostream>
#include <sstream>

class Person {
public:
    void process() {
        // Let's see what we've got in `_request`
        std::cout << _request.rdbuf() << std::endl;

        // Do some processing to produce correponding _response

        // In this example we hardcode the response
       _response << "I'm fine, thanks!";
    }

private:
    std::stringstream _request;
    std::stringstream _response;

    // Make them all friends so that they can access `_request` and `_response`
    friend Person& operator<<(Person& p, std::string const& s);
    friend Person& operator<<(Person& p, std::ostream& (*f)(std::ostream&));
    friend std::ostream& operator<<(std::ostream &o, Person& p);
    friend Person& operator>>(Person& p, std::string& s);
};

Person& operator<<(Person& p, const std::string& s) {
    p._request << s;

    return p;
}

// Notice this peculiar signature, it is required to support `std::endl`
Person& operator<<(Person& p, std::ostream& (*f)(std::ostream&)) {
    p._request << f;

    return p;                           
}

// Somewhat conventional stream operator overload (in terms of signature)
std::ostream& operator<<(std::ostream &o, Person& p) {
    o << p._response.rdbuf();

    return o;
}

Person& operator>>(Person& p, std::string& s) {
    // NOTE: This will read not the whole `_reponse` to `s`, but will stop on
    // the first whitespace. This is the default behavior of `>>` operator of
    // `std::stringstream`.
    p._response >> s;

    return p;
}

達成しようとしている機能に関して、最初の試みは完全に間違っていることに注意してください。これは、ストリーム演算子のオーバーロードに関する従来のチュートリアルに従っているように見えるという事実に要約されますが、ここでは、目的の機能を実現するためにアプローチが異なる必要があります。特に、提案されたストリーム演算子のオーバーロードのシグネチャに注意してください。

さらに、たとえば などの他の入力タイプをサポートするには、オーバーロードを追加する必要がありますint基本的に、標準でstd::basic_ostreamが提供するものと同様のオーバーロードを追加する必要があります。特に、最後のものに注意してください。

basic_ostream& operator<<(basic_ostream& st, 
                          std::basic_ostream& (*func)(std::basic_ostream&));

この男はサポートするためにそこにいstd::endlます。Person適切に機能するように、同様のオーバーロードを既に追加していることに注意してstd::endlください (以下を参照)。プリミティブ型のようなその他のオーバーロードは、演習として残されています。

応答の読み取り

あなたが最初に欲しかったもの。

int main() {
    Person daniel;

    daniel << "Hello" << std::endl;
    daniel << "How " << "are you";
    daniel << " doing?" << std::endl;

    // We are ready to process the request so do it
    daniel.process();

    // And Daniel's answer is...
    std::cout << "Daniel says: " << daniel << std::endl;

    return 0;
}

応答を読む: 別の方法

これはやや不器用で面倒ですが、基本的にはPerson& operator>>(Person& p, std::string& s)オーバーロードの実装のコメントの結果です (上記を参照)。

int main() {
    Person daniel;

    daniel << "Hello" << std::endl;
    daniel << "How " << "are you";
    daniel << " doing?" << std::endl;

    // We are ready to process the request so do it
    daniel.process();

    // And Daniel's answer is...
    std::string part1;
    std::string part2;
    std::string part3;

    // Will read "I'm"
    daniel >> part1;

    // Will read "fine,"
    daniel >> part2;

    // Will read "thanks!"
    daniel >> part3;

    std::cout << "Daniel says: " << part1 << " " << part2 << " " << part3 << std::endl;

    return 0;
}
于 2013-04-27T02:13:54.923 に答える
1

rdbuf() は文字列を返しません。str() を呼び出して、stringstream から std::string を取得する必要があります。プライベート属性にアクセスするには、これら 2 つの関数をクラスのフレンドとして宣言する必要があります。

class Person
{
public:
    void process();

    friend std::ostream& operator<<(std::ostream& o, const person& p);
    friend std::istream& operator>>(std::istream& i, person& p);
private:
    std::stringstream _request;
    std::stringstream _response;
}

std::ostream& operator<<(std::ostream& o, const person& p)
{
    o << p._response.str();

    return (o);
}

std::istream& operator>>(std::istream& i, person& p)
{
    i >> p._request;
    // internal process() call probably will be better
    return i;
}
于 2013-04-27T01:26:15.567 に答える