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

Ian Romanick idr at freedesktop.org
Mon Aug 26 17:17:38 PDT 2013


On 08/26/2013 01:10 PM, Francisco Jerez wrote:
> Ian Romanick <idr at freedesktop.org> writes:
>
>> [...]
>>>> Disadvantage (b) can be made painless with the macro I discuss below.
>>>>
>>>>
>>> IMHO it would be nicer to define generic templates implementing
>>> overloads for all bitwise operators.  They would have to reference the
>>> bitmask_enumeration_traits structure so they would be discarded for
>>> non-bitmask types.
>>> [...]
>>> Second, we could arrange for the expression 'FOO op BAR' (with 'FOO' and
>>> 'BAR' enumerants from different incompatible bitmask types) to be
>>> rejected by the compiler by means of a static assertion in the
>>> definition of 'T op S'.  If we use the macro solution below the compiler
>>> will accept that expression by downgrading both T and S to integers and
>>> then applying the built-in definition of 'op'.  Though it would still
>>> refuse to assign the result to a variable of any of both types *if* the
>>> user is doing that.
>>
>> As a non-C++ programmer, that explanation gave me a headache.  I don't
>> think this project is ready yet for its developers to need that level
>> of knowledge of the C++ type system.
>>
>> I can immediately understand Chad's macro, and I can also (nearly
>> immediately) understand that it's probably not the "C++ way."
>
> My explanation is exactly as relevant if we stick to Chad's solution or
> not, using macros doesn't save you from getting the unexpected effect I
> was trying to describe -- quite the opposite, I can't think of any
> simple way to work around that problem without using templates.
>
> 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;
}

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 can't be right.  Am I missing something?  Or am I reinforcing my 
point about not being ready for this level of C++ ninjitsu...

> The template-based solution might seem somewhat obscure to the
> inexperienced C++ programmer, but unlike the macro-based one it would be
> semantically sound, and this is just one of many reasons why it's a good
> idea for anyone dealing with C++ code to have at least some basic
> knowledge on using templates -- it's the cleanest way to do static
> polymorphism and generic programming in C++.
>
> That said, I agree that it would be a bad idea to make a sudden
> transition to template metaprogramming in components of our tree where
> the majority of maintainers have a strong preference towards old-school
> C programming, but that's no reason to reject a small, non-intrusive and
> potentially useful change in the good direction a priori before having
> seen any of the code...
>
>> [...]



More information about the mesa-dev mailing list