Boost logo

Boost :

From: tobi_at_[hidden]
Date: 2024-03-27 14:01:45


Am 2024-03-26 18:50, schrieb Andrey Semashev via Boost:
> On 3/26/24 18:53, Tobias Loew via Boost wrote:
>> Am 2024-03-25 11:38, schrieb Andrey Semashev via Boost:
>>>
>>> I don't really like the idea of operators in the global namespace. I
>>> would rather prefer if the operators were defined in the library's
>>> namespace, and the enablement was always through the macro. Where the
>>> macro would not just import the operators for lookup but also
>>> "enable"
>>> them for the given enum.
>>
>> 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.

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.
 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.

>> Additionally, there are macros to easily import all operators/utility
>> functions
>> into a namespace (BOOST_FLAGS_USING_OPERATORS(),
>> BOOST_FLAGS_USING_UTILITIES()).
>>
>> I'm not sure what you mean by your last sentence. Do you just ask for
>> a
>> macro, like
>>
>> #define BOOST_FLAGS_ENABLE(Enum) \
>> constexpr inline bool boost_flags_enable(Enum) { return true; } \
>> BOOST_FLAGS_USING_OPERATORS()
>>
>> or something else?
>
> Yes, or something equivalent. I'm not sure this can be made working in
> all contexts, e.g. for enums declared in user's namespaces as well as
> in
> classes and templates, so there may be multiple such macros for
> different use cases or there may be optional arguments or something.
> But
> the effect should be the same - you apply one macro to the enum, and
> that makes bitwise operators work for that enum.
>
> I'm not sure what would be the purpose of the other macros you mention
> (BOOST_FLAGS_USING_OPERATORS, BOOST_FLAGS_USING_UTILITIES). I mean, is
> there a use case for importing the operators but not enabling them? And
> what are the utilities and why one would want a macro to import them?

I though it the other way around: enabling without importing. When
everything is imported into global namespace by default, then it's
only under certain conditions (e.g. the one you pointed out) necessary
to also import into the enum's 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.


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