Domanda

I'm just curious whether it is possible to somehow declare something similar to cout but to define its function. For example:

SetCursorPosition(output_handle, some_COORD);
cout_coord << "Hi\nthere!";

to produce this output:

 .
               Hi
               there!
È stato utile?

Soluzione

You could use operator overloading to make << do basically anything (just google "c++ operator overloading", you'll find tons of information), but such a thing as in your question is generally considered abuse of operator overloading. Overloading operators is intended to make code easier to read. In C++, everyone knows that << means "output something", just like += means "mathematically add something" and = means "assign something".

When I see << in some piece of code, then I certainly don't read it as "set cursor position and then print text". You could implement it like this, but it's bad programming style, akin to misnaming ordinary functions.

Altri suggerimenti

Well cout isn't a function, it's actually a std::ostream. You can create your own ostream that writes to stdout.

The way to implement this logic is to create a custom stream buffer which writes at the opportune location in its overflow() method and then to create a suitable std::ostream using this stream buffer. Here is a rough sketch on how that would look like:

class posbuf: public std::streambuf {
    int d_row;     // current row
    int d_column;  // column where to start output
    void move() { /* use curses, VT100 codes, whatever to move the cursor */ }
    int overflow(int c) {
        if (c == traits_type::eof()) { return traits_type::not_eof(c); }
        if (c == '\n') { ++this->d_row; this->move(); return '\n'; }
        return std::cout << traits_type::to_char_type(c)? c: traits_type::eof();
    }
    int sync() {
        return std::cout.flush()? 0: -1;
    }
public:
    posbuf(int row, int column): d_row(row), d_column(column) { this->move(); }
};
struct oposstream: private virtual posbuf, public std::ostream {
    oposstream(int row, int column): posbuf(row,c column), std::ostream(this) {}
};

int main() {
    oposstream out(4, 10);
    out << "hello\nworld";
}

Except for a couple of likely typos and the details on how to actually move the cursor, the above code should actually work and create an std::ostream which can be passed wherever an std::ostream& is expected. Any attempt to overload the output operator using some templates will not work as well.

Thanks to Christian Hackl and another user that removed their answer I did a research and found the answer I was looking for.

If anyone is still curious my example in the question became:

std::ostream& operator<<(std::ostream& left, const char * right)
{
    string sRight = right;
    CONSOLE_SCREEN_BUFFER_INFO con;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &con);
    COORD xy;
    xy.X = con.dwCursorPosition.X;
    xy.Y = con.dwCursorPosition.Y;
    for (int i = 0; i < sRight.length(); i++)
    {
        if (sRight[i] == '\n')
        {
            xy.Y++;
            SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), xy);                
            continue;
        }
        cout << sRight[i];
    }
    return left;
}

And then you just:

SetConsoleCursorPosition(output_handle, some_COORD);
cout_coord << "Hi\nthere!";

And "Hi" and "there!" are one under the other for every x given with some_COORD!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top