0

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!
user229044
  • 232,980
  • 40
  • 330
  • 338
Bonnev
  • 947
  • 2
  • 9
  • 29

4 Answers4

1

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.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • 2
    In C++, everyone knows that `<<` means "left shift". – Lightness Races in Orbit Mar 01 '14 at 18:13
  • A better way to implement this without mucking around with operators is to create an `ostream` wrapper that formats the output and exposes member functions that allow formatting options to be set, or perhaps uses custom manipulators. A simpler way, depending on requirements, is to just use existing manipulators, like `width()` and the alignment ones. – Jason C Mar 05 '14 at 02:26
0

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

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
wybourn
  • 638
  • 9
  • 29
0

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.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • This is interesting but looks a bit complex, I haven't finished the c++ book and I am not that familiar with some of the functions you use. I WILL look them up but actually I found what I was looking, see my answer on the question. – Bonnev Mar 01 '14 at 21:00
0

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!

Bonnev
  • 947
  • 2
  • 9
  • 29