检查联合是否相等

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

我的Something::operator==的实现似乎相当昂贵和复杂。在具有联合类型的类中检查相等性的唯一方法是这样吗?

还是有更好的方法可以避免分支/检查额外的变量?


尽量避免使用联合体。你可能应该使用模板。或者使用模板和模板特化。 - Some programmer dude
2
@Captain:这里没有未定义的内容——bool 确保只有一个联合成员可以被访问。 - Billy ONeal
1
检查已经很好了,绝不昂贵。有一点需要注意:由于您没有修改对象,因此应将该方法标记为“const”。 - stefan
我最初认为可能会便宜一点,但浮点值意味着你必须检查isFloat。所以不行,你需要检查isFloat。不过请看下面我的答案,那个版本更简洁。 - Sean Perry
4个回答

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

最少的检查使代码清晰易懂且易于调试。您需要编写构造函数和/或设置方法以确保isFloat始终正确。


1
你可以通过用以下代码替换最后两行代码,来去除一个多余的检查,并稍微提高可读性。
if(isFloat != mS.isFloat) return false; // As you have
return isFloat ? mS.k == k : mS.n == n;

(或等效的if结构,如Sean Perry的答案中所述),但编译器可能会很好地优化您的版本。
无法避免运行时检查类型是否匹配。您可以考虑使用现成的辨别联合类型,例如Boost.Variant;它不会更有效率,但使用起来可能更容易且更少出错。

没有办法避免运行时检查类型是否匹配,这就是我想要确定的。谢谢! - Vittorio Romeo
你的解决方案虽然不正确,但我也需要检查mS.isFloat - Vittorio Romeo
@VittorioRomeo:只需按照我说的更换最后两行即可。首先保留第一行以检查类型是否匹配。 - Mike Seymour
我使用if/else结构,因为a)它让代码随时间而适应,b)当我说“那不可能发生”时,它给了我一个在调试器中放置断点的地方。否则,Mike的版本与我的版本相同。我总是使用大括号,因为同样的代码总是会被更新。您可以将它们省略以保持原始的最小风格。 - Sean Perry

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

这并不比OP的问题更便宜或更简单。 - Billy ONeal

0

我认为你无法避免检查所有条件。因此问题可能是如何更简单、更有表现力地编写它们。

我会这样写:

bool operator==( const Something &mS ) const
{
    return  ( ( isFloat == mS.isFloat ) && ( isFloat ? k == mS.k : n == mS.n ) );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接