
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. +1 to the whole. Having macros to select default template params avoids
On 16.12.19 23:43, Gavin Lambert via Boost wrote: the ODR and mixing issues. HOWEVER: What about you set BOOST_USE_THROW=1, then include libraryX then Boost and then use `static_string<char/*, default chosen by macro*/>`? libraryX might redefine BOOST_USE_THROW=0 and you get the wrong type. So IMO either template policy (only) or "stick to your guns". I'm also pro-exception on "overflow". Often enough (especially in hot loops where bounds are usually clear) the optimizer will remove all those. At least, just std::abort.
+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.] Oh yes... Damn shared objects. And with boost::throw_exception opens the door for ODR violations again...