Boost logo

Boost :

From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2024-03-27 16:40:11


On 3/27/24 17:01, Tobias Loew via Boost wrote:
> Am 2024-03-26 18:50, schrieb Andrey Semashev via Boost:
>> On 3/26/24 18:53, Tobias Loew via Boost wrote:
>>>
>>> The library now has a macro-option to prevent importing all operators
>>> into the global
>>> namespace (BOOST_FLAGS_NO_GLOBAL_USING).
>>
>> I think the no-global-namespace should be the only option, and there
>> should be no such macro. Otherwise, there is risk of configuration
>> mismatch and ODR violations.
>>
>> Enums are often used in library interfaces, and offering this
>> configuration macro may pose a problem. For example, if a library A
>> wants to define its public enums with this macro defined, and its user B
>> wants to define its own enums without this macro then there will be a
>> compatibility issue.
>
> Thanks for pointing out this, even though I cannot see ODR violations: the
> definition of the operators/utility functions are always the same and
> reside
> in namespace boost::flags, the import into other namespaces is done via
> using declarations which (IIRC) are irrelevant to ODR.

It may be relevant to ODR if the using-declaration changes the operator
found by name lookup.

> One more word to, why I imported everything into global namespaces: I
> wanted
> the opt-in be a single definition and NOT a macro (just to prove, that it's
> possible). So, to make it work, I had to import all operators/functions
> into
> global namespace.

I understand. But being able to do it doesn't necessarily make it the
best solution. Introducing things in global namespace is rather
intrusive, and it has bitten us in the back in the past. I think,
libraries should avoid putting their stuff in the global namespace at
all costs, and the "enable" macro approach seems like an acceptable
alternative to me.

> From my perspective, this library is more like a core-language extension:
> it introduces flags to the language in a generic way, and therefore
> enhances the global operators with the respective functionality for enabled
> enums.

Even core language extension libraries should avoid polluting the global
namespace. Take existing Boost libraries for example: Boost.ForEach,
Boost.Lambda2, Boost.StaticAssert.

By the way, we already have boost/detail/bitmask.hpp that provides
bitwise operators for enums, and it is also designed to be used in the
enum's namespace (i.e. without polluting the global namespace).

> The utilities are a bunch of functions
> - for handling flags as a multi-dim Boolean algebra: tests for
>   inclusion, intersection
> - easy interface for modifying flags depending on a bool, e.g.
>   make_if(E e, bool set)               for     set ? e : E{}
>   remove_if(E e, E mod, bool remove)   for     remove ? e & ~mod : e
>
> I see them as part of the flags interface, so in my original version of
> the library they were always imported into global namespace. But I wanted
> the import to be optional, in case others see it different.

This sounds more like a collection of algorithms on enums. In this case,
I think, they are better placed in Boost.Flags namespace, and there is
no need to import them, other than to omit the namespace when calling them.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk