On 16/12/2019 21:43, Andrzej Krzemienski wrote:
``` template
void do_something(static_string &str) { // ??? } ``` I do not know what the contract is.
Hiding the decision under a macro doesn't seem an uncontroversial solution either. If I configure the macro to mean "over-resizing is a bug", and I am using a third party library that internally uses `static_string`, and I may not even know about it, and it defines the same macro as "over-resize is fine", I will get a ODR violation and the likely outcome will be that either I or the third party library will get a different behavior than requested.
This is why, as I mentioned elsewhere in a related context, macros should only ever select between different explicitly-named-differently implementations (such as setting a default for that template policy parameter, but not replacing the template policy parameter). Otherwise you get ODR violations and inconsistent ABI. At least when explicitly part of the signature, both implementations can co-exist in the same binary with minimal issues as long as they're kept strictly separate -- and if someone tries to "cross the streams" then they'll get linker errors. Or, as I also said elsewhere, just pick one and stick to your guns. Personally, I prefer throwing exceptions for that case; it's much safer than allowing a buffer overflow.
My recommendation would be to just make a call that over-resizing the string is fine and calls `boost::throw_exception()` and not allow the users to customize it beyond what `boost::throw_exception()` already offers. If I need a library that needs the over-resizing to be a diagnosable bug, i will use a different one (which may be a thin wrapper over `static_string`.
+1. Although throw_exception itself is not entirely immune to the problems above, it is at least a customisation point that only the application author is allowed to touch, which is better than a macro. [Although things get a bit dicier with shared objects and private visibility.]