How to determine if std::filesystem::remove_all failed? - c++

I am trying to use the non-throwing version of std::filesystem::remove_all, I have something like:
bool foo()
{
std::error_code ec;
std::filesystem::remove_all(myfolder, ec);
if (ec.value())
{
// failed to remove, return
return false;
}
}
Is this the correct way to use error_code?
My reasoning:
I read this:
The overload taking a std::error_code& parameter sets it to the OS API
error code if an OS API call fails, and executes ec.clear()
Now here:
clear - sets the error_code to value 0 in system_category
Now I used this to imply error_code == 0 => No error. error_code != 0 => error.
I really can't any much examples of uses of error_code. I just want to determine if all the files have been removed or not.

There is a difference between ec.value() and ec != std::error_code{}; in the case where the error code in ec is a different error category than system error and has a value of 0, the first will return false, while the second will return true.
Error codes are a tuple of categories and value. Looking only at the value is a tiny bit of "code smell".
In this case, I don't think it is possible for the error code to have anything except the system category. And it would be bad form for a non-system error category to use the value 0 for an actual error.
If there was no error (value 0) with a non-system error code, treating it like an error is probably a bad idea. So maybe you shouldn't be checking the category.
Finally, if (ec.value()) is a verbose way of saying if (ec). I'd use the explicit operator bool() const instead of calling .value().
Another option is:
if (-1 == std::filesystem::remove_all(myfolder, ec)) {
// failed to remove, return
return false;
}

Related

Suppress "Avoid unnamed object" warnings for function returns

I have a log function that I sometimes pass the return of on to another function, and sometimes call alone
LogReturnStruct Log(string message) { writeToFile(message); return {message};);
this is because i sometimes want to log something is about to be attempted, as well as if it succeeded or not
void Handle(LogReturnStruct, statusCode)
{
if(statusCode == valid)
Log("sucess: "+ LogReturnStruct.message);
else
Log("failure: "+ LogReturnStruct.message);
}
So i can call something like this
Handle(Log("message"),funcThatMightFail());
and it will enforce logging before and after this call, and will log at least before even if the call raises an exception
I also want to be able to just log a message however
Log("message"); // alone call
However, no matter how i use [[maybe_unused]], i can't seem to suppress the compiler warning
"Avoid unnamed objects with custom creation and destruction"
is there a way to indicate this return value may be unused (and that's ok) without disabling the entire warning?
It seems you might use [[gsl::suppress(es.84)]], but it should be used at call site :-/
MACRO can then help:
LogReturnStruct LogImpl(string message) { writeToFile(message); return {message}; }
#define Log(s) [[gsl::suppress(es.84)]] LogImpl(s)
Cleaner solution is to avoid the warning and create 2 functions (You already have them :) ) (but requires to change call sites):
void Handle(LogReturnStruct, statusCode)
{
if(statusCode == valid)
writeToFile("sucess: "+ LogReturnStruct.message);
else
writeToFile("failure: "+ LogReturnStruct.message);
}
and
Handle(Log("message"), funcThatMightFail());

Best practices for using `std::error_code`

I am currently building an embedded system and use a modern C++ compiler.
While I could technically fit exception handling in the given resources (ARM7, more than 10M RAM), I don’t think exceptions are the right tool for something like this and using exceptions requires RTTI, which in turn results in code bloat.
To stay C++-ish anyway I want to use std::error_code (or similar with more data) because I do like the concept.
However, there does not seem to be any consenus on how to actually use them. I have seen at least four different ways of passing them between function calls, two of them with multiple semantics.
Passing by pointer as an argument
void somefunction(Args..., std::error_code* error);
This is the way I have not seen that often and the one I dislike the most. It leaves the return type fully available and (often, but not always) passing nullptr resulted in normal throwing behaviour.
Passing by reference as an argument
void somefunction(Args..., std::error_code& error);
This is the one I prefer. It leaves returnvalue fully available and makes clear that the error_code is not optional.
Returning it by value
std::error_code somefunction(Ret& out <= if used, Args...);
I have seen this one quite often but don’t really like it that much, as it uses up your return value and I generally don’t like “out parameters” unless there’s no way around them.
Returning a std::variant<Ret, std::error_code>
std::variant<Ret, std::error_code> somefunction(Args...);
This one allows for a return value, but makes accessing both value and error harder. Also, it makes code calling the function more verbose.
Semantics
I have seen both way 1 and 2 with different semantics, if the error_code is passed.
Clear at start and set on error
Only set on error
Return right at start if the error_code is “set”
The last way is pretty good if you want to reduce error checking in the calling code. As you can just pass one error_code to multiple functions without checking in between and everything after the first error will not execute, similar to how exceptions would do it.
I personally do prefer way 2 with checking and returning, however I might be biased.
Is there some recommended / generally accepted way to do it?
Ok, this is no complete answer and actually not perfectly on topic because I am not aware of a standard way to do this. But I once saw a nifty little trick to make error codes harder to misuse. Consider the following code:
struct MyEC {
MyEC() {}
MyEC(MyEC && other) : parent(&other) {
// Maybe log and or abort if other is not checked
other.checked = false;
}
// Delete other constructors and assignment operators
~MyEC() {
if(!checked && parent == nullptr) {
// log and or abort
}
}
[[nodiscard]] std::error_code check() {
checked = true;
return ec;
}
void set(std::error_code err) {
if(parent == nullptr) ec = err;
else parent->set(err);
}
private:
MyEC* parent = nullptr;
checked = true;
std::error_code ec {};
};
int foo(MyEC&& err) {
err.set(/* some error */);
return 5;
}
int foo1(MyEC&&) {
return 4;
}
void bar() {
MyEC err;
foo(std::move(err));
// err has the error code and if its not checked, we will know
foo1(std::move(err));
// even though no error occurs, we will abort if err is not checked.
}
It will even then abort, when the error code is not set but also not checked, which is pretty nice. It has a lot of uses after move, which is a bit weird, but this is no problem here.

If a function returns a certain type, what are my options for returning errors?

In my particular instance, I have a function to calculate a checksum, which returns a uint8_t. What would be options for showing the checksum verification has been unsuccessful? Normally I'd return -1 but obviously not an option. Return an int and cast it?
You have 4 options:
Adding an error state argument that passes by reference and check its state afterwords:
int state = 0;
auto checksum = checksum(data, state);
if(state) //handle error
You can track state in an object that manages the checksum:
CSummer summer;
auto checksum = summer.sum(data);
if(summer.state) //handle error
You can throw exceptions from summer:
uint8_t sum;
try
{
sum = summer(data);
}
catch(const std::exception &ex)
{
//handle error
}
Separate the two functions: have a function to get the checksum and another to verify.
From your question, I am not quite sure if you want to calculate a checksum or want to verify whether a checksum is correct. If you want both, you can-
Use two functions: one for calculating the checksum(returns uint8_t) and the other for verifying if it's correct(returns a Boolean). This is the best way in my opinion.
Return a structure (struct) from your function. The structure will contain a uint8_t(the checksum) and another element telling if the checksum is correct.
Throw an exception.
Modify a global flag.
You should probably decide if you want your return value to indicate failure/success OR the checksum. If you function signature is currently uint8_t calc_checksum(Foo& bar) you could perhaps try changing it to something like bool calc_checksum(Foo& bar, uint8_t& checksum) or bool calc_checksum(Foo& bar, uint8_t* checksum_ptr) where that last parameter is filled with your result and the return result is true if an error occurred. The former allows you to do something like
uint8_t checksum;
if(calc_checksum(bar, checksum)) {
// handle the error in calc_checksum
}
Otherwise you can simply throw an exception. One of the differences is that the method above will silently fail if the return value is not checked, so in that sense exceptions are preferable.

What is the correct way to return an 'Invalid Value' type in C++, without the use of pointers?

I often use -1 as the invalid value type when returning from a function, where the input yields incorrect output. For instance, writing an indexing function where the index is out of bounds, instead of throwing an exception, -1 can be returned. But when writing a function that has negative values as possible return types, this technique does not work. What is the correct way to return an invalid type value in such instances?
The technique I use mostly is to set the return type to be of type *int, and return a Pointer to NULL. But, that requires all return values to be of a pointer type, which seems like an extra overhead to the function. Is there an accepted standard for returning values in such cases?
In newer C++, I'd suggest using std::optional<>; if you don't yet have it, boost::optional<>.
One option would be to let your function take a bool& as an output parameter used to indicate if the returned value is valid.
int myFunc(bool& valid); // sets 'valid' to true if result is usable, false otherwise
Users can then do
bool valid = false;
Int result = myFunc(valid);
if (!valid) {
// Handle error
}
// Use result
Not the most pretty solution, but it does the job.
Apart from the answer I provided above, there's a very clean, continuation-passing solution (given you're non-virtual):
template<typename Success, typename Failed>
void parse( const std::string& str, Success s, Failed f )
{
auto a = start_parse(str);
if( a.problem() )
return f(); // you _might_ have an error code here
s( finish_parse(str, a) );
}
Then you might customize by:
Success:
[&i] (int i_) { i = i_; }
out(i), where out(int& output_) returns the above lambda for output_
actual code doing something useful
function to continue with
Failed:
[&i]{ i = 0; }, `[&i]{ i = nullopt; }, or any other default value
[] { throw MyFavouriteException(); }
retry logic
std::terminate()
[]{} if you don't care (or if you're 100% sure it'll succeed)
It might look a little verbose, but IMHO:
it's trivial to read
any other schematics can be mimicked, even if there's no default c'tor
easy to change as well
'you don't pay for what you don't use', can surely be optimized away
every schematic is visible and apparent from code:
for default value, caller sets it, not callee or global
std::optional<> and default value are handled the same
for exception, caller knows better what to throw
for no action, you don't have to lookup the implementation to know this
for std::terminate(), well, you know what to expect
if you 'speak' CPS, you might actually continue and save an if / catch / etc.
The only issue I see is constructor initializer lists. Any thoughts on this?

Is there an idiom like `if (Value * value = getValue())` when you branch on an expression of the retrieved value?

I am often using the common
if (Value * value = getValue())
{
// do something with value
}
else
{
// handle lack of value
}
Now, I also often do
QString error = someFunctionReturningAnErrorString(arg);
if (!error.isEmpty())
{
// handle the error
}
// empty error means: no error
That's all fine but I would like the error variable to be scoped to the if-block. Is there a nice idiom for that? Obviously, I can just wrap the whole part inside another block.
This, obviously, does not work:
if(QString error = someFunctionReturningAnErrorString(arg), !error.isEmpty())
{
// handle the error
}
// empty error means: no error
And unfortunately (but for good reasons) the QString cannot be converted to bool, so this does not work either:
if(QString error = someFunctionReturningAnErrorString(arg))
{
// handle the error
}
// empty error means: no error
Any suggestions?
No. There is no idiom like this, and there is no syntax like this!
Besides, you have reached the point at which it is no longer worthwhile to make your code more and more obfuscated.
Simply write it as you do now.
If you really don't want the scope leakage, introduce a new scope:
{
const QString error = someFunctionReturningAnErrorString(arg);
if (!error.isEmpty()) {
// handle the error
}
}
// The above-declared `error` doesn't exist down here
I use this pattern quite a lot, though I've been fairly accused of scope-addiction, so take that as you will.
The only way to use that idiom while still keeping your code understandable is if your function returns an object that is convertible to bool in a way that true indicates that you want to take the branch and false means that you do not care about it. Anything else is just going to lead to write-only code.
One such object which may be relevant happens to be boost::optional. Given:
boost::optional<QString> someFunctionReturningAnErrorString(T arg);
You could use the idiom you want in a natural way:
if (auto error = someFunctionReturningAnErrorString(arg)) {
// ...
}
This also has the added benefit where I'd consider an optional error message more semantically meaningful than having to check for an empty error message.
There is basically no clean way to do that.
I'd recommend you just define an extra block around the if, but if you really want to have that exact syntax, a solution could be to declare your own class wrapping QString:
struct ErrorString
{
ErrorString(QString&& s) : s{move(s)} {}
operator bool() {return !s.isEmpty();}
QString s;
};
And then you could write:
if(ErrorString error = someFunctionReturningAnErrorString(arg))
{
// handle the error
}
// empty error means: no error
But I'm not particularly fond of this solution.
You could use:
for(QString error = someFunctionReturningAnErrorString(arg); !error.isEmpty(); /* too bad 'break' is invalid here */)
{
// handle the error
break;
}
but this is ugly, and makes your code hard to read. So please don't.
if(auto message = maybe_filter( getError(arg), [](auto&&str){
return !str.isEmpty();
}) {
}
where maybe_filter takes a T and a test function and returns optional<T>. The optional<T> is empty if evalutating the test function on the T gives you false, and T otherwise.
Or really, modify your error getting API to return an optional string.
You can use a lambda.
auto error_string_handler = [](QString && error) {
if (error.isEmpty()) return;
//...
}
error_string_handler(someFunctionReturningAnErrorString(arg));