C++ Using stringstream after << as parameter

后端 未结 5 1535
Happy的楠姐
Happy的楠姐 2021-01-02 19:20

Is it possible to write a method that takes a stringstream and have it look something like this,

void method(string st         


        
相关标签:
5条回答
  • 2021-01-02 20:12

    Ah, took me a minute. Since operator<< is a free function overloaded for all ostream types, it doesn't return a std::stringstream, it returns a std::ostream like you say.

    void printStringStream(std::ostream& ss)
    

    Now clearly, general ostreams don't have a .str() member, but they do have a magic way to copy one entire stream to another:

    std::cout << ss.rdbuf();
    

    Here's a link to the full code showing that it compiles and runs fine http://ideone.com/DgL5V

    EDIT

    If you really need a string in the function, I can think of a few solutions:

    First, do the streaming seperately:

    stringstream var;
    var << "Text" << intVar << "More text"<<floatvar;
    printStringStream(var);
    

    Second: copy the stream to a string (possible performance issue)

    void printStringStream( ostream& t)
    {
        std::stringstream ss;
        ss << t.rdbuf();
        method(ss.str());
    }
    

    Third: make the other function take a stream too

    0 讨论(0)
  • 2021-01-02 20:16

    Since you know you've got a stringstream, just cast the return value:

    stringstream var;
    printStringStream(static_cast<stringstream&>(var << whatever));
    
    0 讨论(0)
  • 2021-01-02 20:18

    Just to add to the mix: Personally, I would create a stream which calls whatever function I need to call upon destruction:

    #include <sstream>
    #include <iostream>
    
    void someFunction(std::string const& value)
    {
        std::cout << "someFunction(" << value << ")\n";
    }
    
    void method(std::string const& value)
    {
        std::cout << "method(" << value << ")\n";
    }
    
    class FunctionStream
        : private virtual std::stringbuf
        , public std::ostream
    {
    public:
        FunctionStream()
            : std::ostream(this)
            , d_function(&method)
        {
        }
        FunctionStream(void (*function)(std::string const&))
        : std::ostream(this)
        , d_function(function)
        {
        }
        ~FunctionStream()
        {
            this->d_function(this->str());
        }
    private:
        void (*d_function)(std::string const&);
    };
    
    int main(int ac, char* av[])
    {
        FunctionStream() << "Hello, world: " << ac;
        FunctionStream(&someFunction) << "Goodbye, world: " << ac;
    }
    

    It is worth noting that the first object sent to the temporary has to be of a specific set of types, namely one of those, the class std::ostream knows about: Normally, the shift operator takes an std::ostream& as first argument but a temporary cannot be bound to this type. However, there are a number of member operators which, being a member, don't need to bind to a reference! If you want to use a user defined type first, you need to extract a reference temporary which can be done by using one of the member input operators.

    0 讨论(0)
  • 2021-01-02 20:19

    Make your wrapper over std::stringstream. In this new class you can define whatever operator << you need:

    class SSB {
    public:
       operator std::stringstream& () { return ss; }
    
       template <class T>
       SSB& operator << (const T& v) { ss << v; return *this; }
       template <class T>
       SSB& operator << (const T* v) { ss << v; return *this; }
       SSB& operator << (std::ostream& (*v)(std::ostream&)) { ss << v; return *this; }
       // Be aware - I am not sure I cover all <<'s       
    private:
       std::stringstream ss;
    };
    
    void print(std::stringstream& ss)
    {
        std::cout << ss.str() << std::endl;
    }
    
    int main() {
      SSB ssb;
      print (ssb << "Hello" << " world in " << 2012 << std::endl);
      print (SSB() << "Hello" << " world in " << 2012 << std::endl);
    }
    
    0 讨论(0)
  • 2021-01-02 20:20

    For ease of writing objects that can be inserted into a stream, all these classes overload operator<< on ostream&. (Operator overloading can be used by subclasses, if no closer match exists.) These operator<< overloads all return ostream&.

    What you can do is make the function take an ostream& and dynamic_cast<> it to stringstream&. If the wrong type is passed in, bad_cast is thrown.

    void printStringStream(ostream& os) {
        stringstream &ss = dynamic_cast<stringstream&>(os);
        cout << ss.str();
    }
    

    Note: static_cast<> can be used, it will be faster, but not so bug proof in the case you passed something that is not a stringstream.

    0 讨论(0)
提交回复
热议问题