I'm trying to figure out the proper way of using the noexcept
attribute. I've already spent half a day trying to understand it, but I'm not sure I did. And I don't want to use or not to use noexcept
everywhere mindlessly.
Question: Do I understand it right, that if a function calls only functions that have noexcept
attribute, then we may (or should) safely mark our function as noexcept
too?
Suppose, I have functions that check whether a provided path exists and is a directory. I use filesystem
for that purpose. One function (IsDir
) calls exists
and is_directory
functions that are not marked as noexcept
. The other function (IsDir2
) calls exists
and is_directory
functions that are marked as noexcept
. Can I safely mark the second function as noexcept
?
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
bool IsDir(const fs::path& p) {
const bool exists{ fs::exists(p) }; // Not marked as "noexcept".
const bool is_dir{ fs::is_directory(p) }; // Not marked as "noexcept".
return exists && is_dir;
}
bool IsDir2(const fs::path& p, std::error_code& ec) noexcept {
const bool exists{ fs::exists(p, ec) }; // "noexcept" version.
const bool is_dir{ fs::is_directory(p, ec) }; // "noexcept" version.
return exists && is_dir;
}
int main () {
const fs::path p("~/Some_Path");
std::cout << std::boolalpha << IsDir(p) << std::endl;
std::error_code ec;
std::cout << IsDir2(p, ec) << std::endl;
return 0;
}
There are 2 scenarios when you'd want to mark a function:
std::terminate
, if an exception would otherwise "escape" the function.If only the former is the desired effect, there are several things that you need to take into consideration:
noexcept
in all scenarios. Some libraries are pre-C++11 compatible and the keyword wasn't even available. Some libraries didn't want to risk ABI breaks or didn't consider it worth the effort adding the keyword in. Some libraries need to be compatible with C, where the keyword isn't available; this includes functions in the C++ standard library such as std::strlen
. In some cases where templates are involved, the required conditional noexcept
specification could get too complicated for the implementor to bother.In your IsDir2
your analysis regarding no exception being thrown inside the function body, so marking it as noexcept
is appropriate, but as noted by @paxdiablo in the comments the implementation of the function may require an overhaul.