Frage

struct Something {
    union {
        float k;
        int n;
    };

    bool isFloat;

    bool operator==(const Something& mS)
    {
        if(isFloat != mS.isFloat) return false;
        if(isFloat && mS.k == k) return true;
        if(!isFloat && mS.n == n) return true;
    }
};

My implementation of Something::operator== seems rather expensive and convoluted. Is this the only way to check equality in classes with union types?

Or is there a better way that avoids branches/checking additional variables?

War es hilfreich?

Lösung

bool operator==(const Something& mS)
{
    if (isFloat != mS.isFloat)
    {
        return false;
    }
    else if (isFloat)
    {
        return mS.k == k;
    }
    else
    {
        return mS.n == n;
    }
}

Clear and debuggable with the minimum number of checks. You want to have a constructor and/or set methods to ensure isFloat is correct at all times.

Andere Tipps

You can remove one redundant check, and perhaps enhance readability slightly, by replacing the last two lines with

if(isFloat != mS.isFloat) return false; // As you have
return isFloat ? mS.k == k : mS.n == n;

(or the equivalent if construct, as in Sean Perry's answer) but the compiler will probably do just as good a job of optimising your version.

There's no way to avoid a runtime check that the types match. You might consider a ready-made discriminated union type like Boost.Variant; it won't be any more efficient, but it might be easier and less error-prone to use.

return (isFloat && mS.isFloat && k==mS.k) || (!isFloat && !mS.isFloat && n==mS.n);

I do not think that you can escape checking all the conditions. So the question can be how to write them more simpler and expressively.

I would write them the following way

bool operator==( const Something &mS ) const
{
    return  ( ( isFloat == mS.isFloat ) && ( isFloat ? k == mS.k : n == mS.n ) );
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top