In C++ std:: streams, after a failure, how to get a failure reason? Required: threadsafe and common to Windows and Linux (or at least Msvc/Gcc)

in c
bitwise operator in c
logical operators in c
ternary operator in c
conditional operator in c
assignment operators in c
sign in c
relational operators in c

Sorry for weird title. Limited to 150 chars so couldn't use proper sentences.

So let's say I've done the following to find out that something went wrong with my file stream:

std::ofstream ofs;
do_stuff_with(ofs);
// streams don't throw on error because C++ [edit: we can make them do so, but the .what()s aren't very user-friendly]
// so we have to check for failure manually
if(!ofs){
    auto fail_code = errno; // threadsafe on Win/Linux
    // but what goes here?
}

1) strerror: Not threadsafe

2) strerror_s: Not in GCC? Or is it?

3) strerror_r: Not in Msvc? Or is it?

4) #ifdef/#define/etc: yuck, but may be the only choice

I did do some searching but I didn't find a "this will definitely work in a sensible yet slightly platform-dependent way" answer... That said, I feel like this is "obviously a duplicate question", but I can't find the original...

You can always throw your own exceptions using std::system_error:

#include <cerrno>
#include <fstream>
#include <iostream>
#include <system_error>

int main()
{
    try
    {
        std::ofstream foo{"/root/bar.baz"};
        foo << "bla" << std::endl;
        foo.close();

        if(!foo)
            throw std::system_error{errno, std::generic_category()};
    }
    catch(const std::system_error& err)
    {
         std::cout << "Error: " << err.code() << " - " << err.what() << std::endl;
    }

    return 0;
}

This returns Error: generic:13 - Permission denied.

C - Operators, The # at the beginning of a line with a text with it is a “preprocessor directive”. It is a software piece that performs several text transformations to your code before sending it to the actual compiler. For example, when you do something like: #define PI 3.141592654. = Simple assignment operator. Assigns values from right side operands to left side operand C = A + B will assign the value of A + B to C += Add AND assignment operator. It adds the right operand to the left operand and assign the result to the left operand. C += A is equivalent to C = C + A

Since C++11, you can use the class std::error_code for that:

std::cout << std::error_code{errno, std::generic_category()}.message();

In fact you can even do it a little shorter than that:

std::cout << std::generic_category().message(errno);

Though I must say I find the first one a little more idiomatic.

As a sidenote, there is also std::system_category(), which seems to be largely equivalent to generic_category() on Unix but on Windows, it can be used to translate Windows API error codes such as returned by GetLastError() etc.

This is the same class that's also used within the std::system_error exception, but you don't need to create an instance of the exception if all you want to do is to get the error message.

Operators in C and C++, isn't a bitwise operator, because * isn't. But some compound operators are bitwise - for example, the &= operator is bitwise, since & is. An Arrow operator in C/C++ allows to access elements in Structures and Unions.It is used with a pointer variable pointing to a structure or union.The arrow operator is formed by using a minus sign, followed by the geater than symbol as shown below.

This is the best I could come up with. It's the "yuck" answer, but at least you can put the "yuck" in a single function and hide it away in some cpp file somewhere. std::ios covers boost streams as well, of course.

Requires #ifdefs so it's a cheat. I believe Visual Studio #defines _WIN32 by default, so at least you don't have to set up that infrastructure per se.

void check_stream(std::ios & stream)
{
    if (!stream){
        char err[1024] = { 0 };
#ifdef _WIN32
        strerror_s(err, errno);
#else
        strerror_r(errno, err, 1024);
#endif
        throw MyException(err);
    }
}

My own solution makes me sad so hopefully a better one will come along. But time is finite, so just submit to the Dark Side, use something like this, and get on with your life. :P

try{
    boost::filesystem::ifstream ifs("testfile");
    check_stream(ifs);
}
catch (std::exception & e){
    std::cout << e.what(); // "No such file or directory"
}

Operators in C / C++, provides constructs that map efficiently to typical machine instructions. Left Shift and Right Shift Operators in C/C++ << (left shift) Takes two numbers, left shifts the bits of the first operand, the second operand decides the number of places to shift. Or in other words left shifting an integer “x” with an integer “y” (x<<y) is equivalent to multiplying x with 2^y (2 raise to power y).

What does # mean in C?, and ## Operators in C. Stringizing operator (#). This operator causes the corresponding actual argument to be enclosed in double quotation marks. Bitwise Operators in C Programming In this tutorial you will learn about all 6 bitwise operators in C programming with examples. In arithmetic-logic unit (which is within the CPU), mathematical operations like: addition, subtraction, multiplication and division are done in bit-level.

What exactly does "*=" mean in C programming?, It's equivalent to: rot = rot * 5;. It's part of a family of operators called 'compound assignment' operators. You can see the full list of them here:  Declarations in C are expression-centric, meaning that the form of the declaration should match the form of the expression in executable code. For example, suppose we have a pointer to an integer named p. We want to access the integer value pointed to by p, so we dereference the pointer, like so: x = *p;

C Operators, C language supports a rich set of built-in operators. An operator is a symbol that tells the compiler to perform certain mathematical or logical manipulations. The modulus operator is useful in a variety of circumstances. It is commonly used to take a randomly generated number and reduce that number to a random number on a smaller range, and it can also quickly tell you if one number is a factor of another.

Comments
  • You can make stream throw on error if you want.
  • The closest you can get in c++ is std::io_errc
  • "// streams don't throw on error because C++". Not that it is guaranteed to have a useful what().
  • Ah I knew about the exceptions() thing, but for some reason I had the idea that it wasn't properly implemented either. But it seems to work, just it gives messages like "ios_base::failbit set" rather than "No such file or directory." as discovered elsewhere on stackoverflow stackoverflow.com/questions/17337602/…
  • check out throw, what(), try and catch.
  • I think std::system_error may be what I've been looking for! I'll try this and then mark this as the answer if it turns out to satisfy my requirements.
  • I edited in a snippet for getting the error message without going via an exception, too, since one of my main issues was getting a readable message out (rather than throwing exceptions, though that's also useful).