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

Francisco Jerez currojerez at riseup.net
Mon Aug 26 17:55:21 PDT 2013


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...
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 229 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20130826/bbe64570/attachment.pgp>


More information about the mesa-dev mailing list