字符串类的接口(interface)通常具有名为IsEmpty(VCL)或empty(STL)的方法。这是绝对合理的,因为这是特例,但是使用这些方法的代码通常必须否定该谓词,这会导致“光学(甚至是心理上的开销)” (感叹号不是很明显,特别是左括号后)。例如,查看以下(简化)代码:

/// format an optional time specification for output
std::string fmtTime(const std::string& start, const std::string& end)
{
    std::string time;
    if (!start.empty() || !end.empty()) {
        if (!start.empty() && !end.empty()) {
            time = "from "+start+" to "+end;
        } else {
            if (end.empty()) {
                time = "since "+start;
            } else {
                time = "until "+end;
            }
        }
    }
    return time;
}

它有四个否定词,因为空的情况是要跳过的情况。在设计接口(interface)时,我经常观察到这种否定,不是一个大问题,却很烦人。我只希望支持编写易于理解的代码。希望您能理解我的观点。

也许我只是被盲目震惊:您将如何解决上述问题?

编辑:在阅读了一些评论之后,我认为有必要说一下原始代码使用了VCL的System::AnsiString类。此类提供了IsEmpty方法,该方法非常易读:
 if (text.IsEmpty()) { /* ... */ } // read: if text is empty ...

如果不被否定:
 if (!text.IsEmpty()) { /* ... */} // read: if not text is empty ...

...而不是如果文本不为空。我认为字面is最好留给读者幻想,也可以使求反效果良好。好吧,也许不是一个普遍的问题...

最佳答案

在大多数情况下,您可以颠倒ifelse的顺序以清理代码:

const std::string fmtTime(const std::string& start, const std::string& end)
{
    std::string time;
    if (start.empty() && end.empty()) {
        return time;
    }

    if (start.empty() || end.empty()) {
        if (end.empty()) {
            time = "since "+start;
        } else {
            time = "until "+end;
        }
    } else {
        time = "from "+start+" to "+end;
    }
    return time;
}

甚至在进行一些重构后变得更加干净:
std::string fmtTime(const std::string& start, const std::string& end)
{
    if (start.empty() && end.empty()) {
        return std::string();
    }

    if (start.empty()) {
        return "until "+end;
    }

    if (end.empty()) {
        return "since "+start;
    }

    return "from "+start+" to "+end;
}

并且为了实现最终的紧凑性(尽管我更喜欢以前的版本,因为其可读性强):
std::string fmtTime(const std::string& start, const std::string& end)
{
    return start.empty() && end.empty() ? std::string()
         : start.empty()                ? "until "+end
         :                  end.empty() ? "since "+start
                                        : "from "+start+" to "+end;
}

另一种可能性是创建一个辅助函数:
inline bool non_empty(const std::string &str) {
  return !str.empty();
}

if (non_empty(start) || non_empty(end)) {
...
}

关于c++ - “empty”的对面是否简洁?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21882655/

10-11 03:42