Program-startup called functions (e.g static variables constructors) must not throw.
For instance :
struct type
{
type() { throw std::runtime_error("type::constructor"); }
} static const g_type_var; // will crash
auto main(int ac, char *av[]) -> int
{}
will cause a crash (uncaught exception) when the program start.
For instance, when using a static const std::regex.
According to en.cppreference.com std::regex documentation, every constructors but default, copy and move may throw std::regex_error exceptions if the supplied regular expression is not valid.
Enforcement :
Global variables constructors must not throw (__declspec(nothrow), throw(), noexcept(true), or noexcept)
No, because that would prevent ever having a global vector or string that is initialized with data, because they aren't noexcept.
If your program throws on startup then fix it e.g. don't hardcode invalid regular expressions into your globals. This doesn't need a guideline.
On large companies code-base, that mix legacy and modern cpp (and thus best-practices), it is not so easy to find out such issue, as static-analysis tools do not cover it.
Such companies rely on the core guideline to improve their code-base quality, and identify fallible code.
This suggestion (nothrow) include the whole constructor context, including what may come from templates arguments.
Only std::vector
For std::string, same case, plus constructor (3).
I understand which functions can throw. My point is that this can throw:
const std::string a_global_string = "some important information";
So it would be banned by your suggestion. I'm saying the problem you describe is not important enough to ban such things. It's simply not a big problem that affects many people, or causes real problems.
I think GuillaumeDua wants to make an exception for allocations. Everything else should be banned/diagnosed.
How does a static analysis tool tell if a global object is going to throw because of allocation failure or throw because of something else?
And that's not what this suggests:
Global variables constructors must not throw (__declspec(nothrow), throw(), noexcept(true), or noexcept)
How does a static analysis tool tell if a global object is going to throw because of allocation failure or throw because of something else?
Possibilities that might work, but are not super nice:
new and other known operations.Minor, but @JonasToth please use allow/deny list to be culturally sensitive.
Sorry English is not my mother tongue. Did not want to offend!
Several rules already mention that global variables should be avoid.
My suggestion was to extend this advise to an exception-free context while constructing such variables.
Of course, as @jwakely spotlighted it, bad allocations may append.
Thus, you are right : we cannot ban such mecanics.
However, we can warn about it, as advise/best-practice.
A less drastic way would be : "Static const variables's constructors should not throw".
Why allow the "allocation" functions and not the rest?
If an organization wants to further supplant the rules with more restrictions, they can do that. However, for the Core Guidelines, I think we need to be facing a more fundamental programming problem. If you avoid global non-const variables, what else remains in your actual codebase?
If the global initialization ended up throwing an exception, it must be for some reasons - just banning the exceptions won't solve that problem.
Thank you for the suggestion! Per our editors' discussion, we generally don't provide guidelines for errors that a compiler would diagnose. And also, we believe that this rule would be very hard to enforce.
We feel that I.22 sufficiently covers this issue.
Microsoft's C++ Core Checker, at least, provides a diagnostic for this case.
Most helpful comment
I understand which functions can throw. My point is that this can throw:
So it would be banned by your suggestion. I'm saying the problem you describe is not important enough to ban such things. It's simply not a big problem that affects many people, or causes real problems.