[Kde-bindings] Qyoto: new features

Richard Dale richard.dale at telefonica.net
Mon Apr 9 22:48:57 UTC 2012


On Monday, April 09, 2012 11:26:09 PM Richard Dale wrote:
> On Monday, April 09, 2012 09:35:31 PM Richard Dale wrote:
> > On Monday, April 09, 2012 01:27:35 PM Dimitar Dobrev wrote:
> > 
> > It works because while QFlags are not technically enums, they do nothing
> > but provide type safety for C++ enums, that is, practically they are
> > enums. On the C# side, enums are natively type-safe so it is completely
> > correct to replace QFlags with Enum.
> > 
> > 
> > Well no I don't think that's right. If you pass 'EnumA & EnumB' as a
> > argument that value isn't an enum, it is an unsigned int. The QFlags stuff
> > is about constructing unsigned ints from enums that are AND'd and OR'd
> > together in a type safe manner.
> 
> Here is my crappy attempt to do something like the Qt QFlags class in C#:
> 
> /*
> C++ QFlags class from qglobal.h:
> 
> template<typename Enum>
> class QFlags
> {
>     typedef void **Zero;
>     int i;
> public:
>     typedef Enum enum_type;
>     inline QFlags(const QFlags &f) : i(f.i) {}
>     inline QFlags(Enum f) : i(f) {}
>     inline QFlags(Zero = 0) : i(0) {}
>     inline QFlags(QFlag f) : i(f) {}
> 
>     inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; }
>     inline QFlags &operator&=(int mask) { i &= mask; return *this; }
>     inline QFlags &operator&=(uint mask) { i &= mask; return *this; }
>     inline QFlags &operator|=(QFlags f) { i |= f.i; return *this; }
>     inline QFlags &operator|=(Enum f) { i |= f; return *this; }
>     inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; }
>     inline QFlags &operator^=(Enum f) { i ^= f; return *this; }
> 
>     inline operator int() const { return i; }
> 
>     inline QFlags operator|(QFlags f) const { QFlags g; g.i = i | f.i;
> return g; }
>     inline QFlags operator|(Enum f) const { QFlags g; g.i = i | f; return g;
> } inline QFlags operator^(QFlags f) const { QFlags g; g.i = i ^ f.i; return
> g; }
>     inline QFlags operator^(Enum f) const { QFlags g; g.i = i ^ f; return g;
> } inline QFlags operator&(int mask) const { QFlags g; g.i = i & mask;
> return g; }
>     inline QFlags operator&(uint mask) const { QFlags g; g.i = i & mask;
> return g; }
>     inline QFlags operator&(Enum f) const { QFlags g; g.i = i & f; return g;
> } inline QFlags operator~() const { QFlags g; g.i = ~i; return g; }
> 
>     inline bool operator!() const { return !i; }
> 
>     inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i
> == int(f) ); }
> };
> */
> 
> 
> using System;
> 
> public class QFlags<T> where T : struct
> {
>     public uint i;
>     public QFlags(T flags) {
>         i = Convert.ToUInt32(flags);
> 	// Throw an exception if this conversion fails
>     }
> 
>     public static uint operator|(QFlags<T> f1, T f2) {
>       uint i2 = Convert.ToUInt32(f2);
> 	// Throw an exception if this conversion fails
>       return f1.i | i2;
>     }
> 
>     public static uint operator&(QFlags<T> f1, T f2) {
>       uint i2 = Convert.ToUInt32(f2);
> 	// Throw an exception if this conversion fails
>       return f1.i & i2;
>     }
> }
> 
> 
> public class FlagsTest
> {
>     public enum MyEnum : uint {
>         ValA = 0x0,
>         ValB = 0x1,
>         ValC = 0x2,
>         ValD = 0x4
>     }
> 
>     static public void Main()
>     {
>         QFlags<MyEnum> f1 = new QFlags<MyEnum>(MyEnum.ValB);
>         uint f2 = f1 | MyEnum.ValC;
>         Console.WriteLine(f2);
>     }
> }

And another attempt:

using System;

public class QFlags<T> where T : struct
{
    public uint i;
    public QFlags(T flags) {
        i = Convert.ToUInt32(flags); 
	// Throw an exception if this conversion fails
    }

    public override string ToString() {
	return i.ToString();
    }

    public QFlags(uint flags) {
        i = flags; 
	// Throw an exception if this conversion fails
    }

    public static QFlags<T> operator|(QFlags<T> f1, T f2) { 
      uint i2 = Convert.ToUInt32(f2);    
	// Throw an exception if this conversion fails
      return new QFlags<T>(f1.i | i2);
    }    

    public static QFlags<T> operator&(QFlags<T> f1, T f2) { 
      uint i2 = Convert.ToUInt32(f2);    
	// Throw an exception if this conversion fails
      return new QFlags<T>(f1.i & i2);
    }    
}


public class FlagsTest
{
    public enum MyEnum : uint {
        ValA = 0x0,
        ValB = 0x1,
        ValC = 0x2,
        ValD = 0x4
    }
      
    public void MyMethod(QFlags<MyEnum> flags) {
        Console.WriteLine(flags);
    }

    static public void Main()
    {
        FlagsTest test = new FlagsTest();
        QFlags<MyEnum> f1 = new QFlags<MyEnum>(MyEnum.ValB);
        QFlags<MyEnum> f2 = f1 & MyEnum.ValC;
	test.MyMethod(f2 | MyEnum.ValD);
    }
}

-- Richard


More information about the Kde-bindings mailing list