1
if ( hFileConnection == INVALID_HANDLE_VALUE ) {
    std::stringstream s;
    s << __func__ << " had GetLastError = " << GetLastError() << endl;
    OutputDebugStringA( s.str().c_str() );
    OutputDebugStringA( "\n" );
}

I like readability of the << operator but I wonder if there better way to pipe it out to the debug, rather than s.str().c_str() ?

My visual studio "unit test" shows "Init had GetLastError = 2" on debug window, so the code does work.

Ian Tubman
  • 65
  • 1
  • 7
  • 1
    Rare case where a macro is reasonable – john Sep 19 '18 at 09:17
  • Can you have another version of `OutputDebugStringA` which takes a `std::string`? – Colin Sep 19 '18 at 09:17
  • 1
    @Colin I doubt that's possible since `OutputDebugString` is a WIN32 API function and is probably `extern "C"` which prevents overloading. – john Sep 19 '18 at 09:18
  • Possible duplicate of [stringstream, string, and char\* conversion confusion](https://stackoverflow.com/questions/1374468/stringstream-string-and-char-conversion-confusion) – fhaus Sep 19 '18 at 09:19
  • 3
    Note that you need to be careful about `GetLastError` and evaluation order. It's safest to store it in a variable before doing anything else. – molbdnilo Sep 19 '18 at 09:42
  • 1
    You could also create a class with a suitable set of overloads of `operator<<()`, that all call `OutputDebugStringA()` as required. Then, given an instance of that class, all you would need to do in your example is `if (hFileConnection == INVALID_HANDLE_VALUE ) {instance << __func__ << " had GetLastError = " << GetLastError() << endl << "\n";}`. Have that class's member functions manage `stringstream` objects if/as needed rather than forcing that onto calling code. Optionally make the class a singleton. – Peter Sep 19 '18 at 09:48
  • @john `extern "C"` doesn't prevent overloading, see this answer: https://stackoverflow.com/a/4866087/8964493 – joe_chip Sep 19 '18 at 09:57
  • @joe_chip interesting i didn't know that. However deliberately overloading a function in a 3rd party API is dubious in any case. molbdnilo's approach is best – john Sep 19 '18 at 10:08
  • @john I agree with you, just wanted to point out it's possible. – joe_chip Sep 19 '18 at 10:16
  • @Colin I found cerr and clog are nice to use, but both go some where else rather than the debug window. – Ian Tubman Sep 19 '18 at 19:46

1 Answers1

5

Make your own interface by writing a little bit of code.

void OutputDebug(const char* s)
{
    OutputDebugStringA(s);
}

void OutputDebug(const std::string& s)
{
    OutputDebug(s.c_str());
}

void OutputDebug(const std::stringstream& s)
{
    OutputDebug(s.str());
}


if ( hFileConnection == INVALID_HANDLE_VALUE ) {
    std::stringstream s;
    s << __func__ << " had GetLastError = " << GetLastError() << endl;
    OutputDebug(s);
    OutputDebug("\n");
}

If you want to get fancy, you can add a little type and overload operator<<.

Even something simple and incomplete like this could prove useful and is sometimes all the fanciness you need:

// Empty types are surprisingly useful.
// This one is only a "hook" that we can attach 'operator<<' to
// in order to use stream insertion syntax.
struct DebugOutput {};  

template<typename T>
DebugOutput& operator<<(DebugOutput& lhs, const T& rhs)
{
    std::stringstream ss;
    ss << rhs;
    OutputDebugStringA(ss.str().c_str());
    return lhs;
}

int main()
{
    DebugOutput debug;
    debug << "hello" << 23 << "\n";
}
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • According to [this answer](https://stackoverflow.com/questions/1374468/stringstream-string-and-char-conversion-confusion), `s.str().c_str()` won't work. – Praneeth Peiris Sep 19 '18 at 09:22
  • 4
    @PraneethPeiris That's a different situation. `OutputDebugStringA` doesn't store the pointer for later, so it will not become invalid. (It's valid in the entire "full-expression".) – molbdnilo Sep 19 '18 at 09:24
  • @PraneethPeiris The other answer is about the situation `const char* str = s.str().c_str(); OutputDebugStringA(str);`, which does have lifetime problems. – molbdnilo Sep 19 '18 at 10:45