[Mesa-dev] [RFC PATCH] i965: Allow C++ type safety in the use of enum brw_urb_write_flags.

Eric Anholt eric at anholt.net
Tue Aug 27 15:10:56 PDT 2013


Francisco Jerez <currojerez at riseup.net> writes:

> Ian Romanick <idr at freedesktop.org> writes:
>
>> On 08/26/2013 01:10 PM, Francisco Jerez wrote:
>>>[...]
>>> The thing is that defining bitwise operators separately for each enum
>>> type, as this patch and the macro solution do, doesn't stop the compiler
>>>  From using the corresponding built-in integer operators when it doesn't
>>> find a match among the user-defined ones.  That means that if we have
>>> two bitfield enumerants from two different disjoint types
>>> e.g. "SEASON_OF_THE_YEAR_SUMMER" and a "CPU_ARCHITECTURE_I386", the
>>> compiler is still going to accept expressions like
>>> "SEASON_OF_THE_YEAR_SUMMER | CPU_ARCHITECTURE_I386", which might not be
>>> what had been expected if the BRW_CXX_ENUM_OPS macro was used in an
>>> attempt to improve the code's type safety.
>>
>> This sounds insane.
>>
>> If there are no operator overloads, the compiler rejects:
>>
>> enum foo f(enum foo a, enum foo b)
>> {
>>     return a | b;
>> }
>>
>
> Here both a and b would be implicitly converted to integers which are
> then or'ed together using the built-in '|' operator yielding an integer.
> Using the result as return value of your "enum foo" function fails
> because in C++ integers are not implicitly convertible to enum types.
>
>> Then we add operloads:
>>
>> enum foo operator|(enum foo, enum foo);
>> enum bar operator|(enum bar, enum bar);
>>
>> And now the compiler will accept:
>>
>> unsigned f(enum foo a, enum bar b)
>> {
>>     return a | b;
>> }
>>
> That's accepted because both a and b are converted to integers as
> before, giving an integer as result, which can be implicitly converted
> to your unsigned return type just fine.  It's easy to avoid that though
> by defining a general overload:
>
> template<typename T, typename S> T operator|(T, S);
>
> for any bitfield types "T" and "S" that includes a static assertion
> within its definition to make sure that both types are indeed the same.
>
> In your example above the compiler would find an exact match during
> overload resolution (our "operator|<foo, bar>(foo, bar);") so it
> wouldn't have to bother with implicit argument conversions.  The
> instantiation of that template would fail thanks to the static assertion
> requiring both T and S to be equal.
>
> I hope this makes the idea a bit clearer.
>
>> That can't be right.  Am I missing something?  Or am I reinforcing my
>> point about not being ready for this level of C++ ninjitsu...

This is way overcomplicated.  I think we're doing just fine with the
status quo of #defines for our bitfields with namespaced names.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20130827/fb1b3290/attachment.pgp>


More information about the mesa-dev mailing list