Vittorio Romeo
Vittorio Romeo

Reputation: 93324

Checking union equality

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?

Upvotes: 3

Views: 124

Answers (4)

Mike Seymour
Mike Seymour

Reputation: 254621

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.

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 311048

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 ) );
}

Upvotes: 0

Sean Perry
Sean Perry

Reputation: 3886

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.

Upvotes: 3

timrau
timrau

Reputation: 23058

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

Upvotes: 0

Related Questions