+ 5

[ANSWERED] Overloading the << operator for conducting checks before output to STDOUT

I am trying to make a Button Class to print certain boxes on a text based console window in Windows that may be interfaced with by the user by actions like hovering on it, clicking it, etc. I also made a Console class to handle console properties like Size, Foreground and Background Text Colors, Cursor Positions for Printing, etc. Now, I want to prevent the << operator to print on the button or any such element. So, I created a vector of 4 points to store the area of the Button and tried to overload << to check before output that the current cursor position does not lie on the buttons : template <typename T> std::ostream& operator<<(std::ostream& os, T obj) { // SMALL_RECT is a struct of 4 points. Console::Reserved() returns the vector with all // the saved area points. std::vector<SMALL_RECT> Res = Console::Reserved(); CONSOLE_SCREEN_BUFFER_INFO cb; GetConsoleScreenBufferInfo(Console::Out(),&cb); COORD c = cb.dwCursorPosition; for(SMALL_RECT s : Res) { if((c.X>=s.Left||c.X<=s.Right)||(c.Y>=s.Top||c.Y<=s.Right)) throw std::logic_error(">> Console : Space reserved for UI Element!"); } os<<obj; return os; } However, the overload failed, as when I tried printing a single character somewhere else on the console, I got a lot of errors, like the following : error: ambiguous overload for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'const unsigned char') error: ambiguous overload for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'std::__cxx11::string {aka std::__cxx11::basic_string<char>}') Why do these errors occur? Is there a solution? If not, is there another way I can achieve a similar result?

15th Jul 2018, 9:20 AM
Solo Wanderer 4315
Solo Wanderer 4315 - avatar
2 odpowiedzi
+ 3
I think David Rodriguez's answer, ( the second answer ) here is a good explanation as to why the ambiguity is triggered. https://stackoverflow.com/questions/5319190/ambiguous-overload-for-operator-in-stdcout You could make a wrapper which temporarily holds the value and write the operator<< overload for that wrapper which does the appropriate checks and then calls the temporarily holded values' operator<<. No ambiguity there. Or you could scrap the operator<< entirely and go for a Console::Write function or something. Anyway here is kinda the idea: #include <iostream> template<typename T> struct wrapper { const T& obj; template<typename U> friend std::ostream& operator<<( std::ostream& os, const wrapper<U>& o ); }; template<typename U> std::ostream& operator<<( std::ostream& os, const wrapper<U>& o ) { if( 0 ) throw std::logic_error( "Blablabla" ); return os << o.obj; } int main() { wrapper<char> w{ 'T' }; std::cout << w; }
15th Jul 2018, 10:49 AM
Dennis
Dennis - avatar
+ 1
Dennis Thank you very much for answering my question. I'll try this approach and let you know. Edit : The wrapper approach worked for me. Thanks a lot.
15th Jul 2018, 12:07 PM
Solo Wanderer 4315
Solo Wanderer 4315 - avatar