是否有更短的方式编写`StringPtr? StringPtr:“null”`?

时间:2011-08-16 19:25:49

标签: c++ conditional-operator

我有这段代码:

 std::wstringstream outstream;
 outstream << (prop.m_pwszOriginalVolumeName 
             ? prop.m_pwszOriginalVolumeName 
             : L"null") << L";"
           << (prop.m_pwszSnapshotDeviceObject 
             ? prop.m_pwszSnapshotDeviceObject 
             : L"null") << L";"
           << (prop.m_pwszOriginatingMachine 
             ? prop.m_pwszOriginatingMachine
             : L"null") << L";"
           << ... // some more strings here

有没有办法避免代码重复,仍然有简洁的代码?

5 个答案:

答案 0 :(得分:6)

您可以定义一个小函数:

whatever_t strOrNull(whatever_t str) {
    return str ? str : L"null";
}

然后您的代码变为

std::wstringstream outstream;
outstream << strOrNull(prop.m_pwszOriginalVolumeName)   << L";"
          << strOrNull(prop.m_pwszSnapshotDeviceObject) << L";"
          << strOrNull(prop.m_pwszOriginatingMachine)   << L";"
          << ... // some more strings here

或者,如果您想要更简洁,可以执行此操作(取决于whatever_t是什么;如果wstringstream已经为该类型设置了operator<<,则会赢得此优惠工作):

wstringstream& operator<<(wstringstream& out, whatever_t str) {
    if (str)
        out << str;
    else
        out << L"null";

    return out;
}

然后您的代码变为

std::wstringstream outstream;
outstream << prop.m_pwszOriginalVolumeName   << L";"
          << prop.m_pwszSnapshotDeviceObject << L";"
          << prop.m_pwszOriginatingMachine   << L";"
          << ... // some more strings here

答案 1 :(得分:2)

一个函数,或一个lambda:

auto foo = [](const wchar * p) { return p ? p : L"null;" };

outstream << foo(prop.m_pwszOriginalVolumeName) << L";"
          << foo(prop.m_pwszSnapshotDeviceObject) << L";"
          << ...etc...

答案 2 :(得分:2)

一个简单的功能应该可以解决问题。

wchar_t* filterNullString(wchar_t* str)
{
  static wchar const* nullStr = L"null";
  return str ? str : nullStr;
}

std::wstringstream outstream;
outstream << filterNullString(prop.m_pwszOriginalVolumeName) << L";"
           << filterNullString(prop.m_pwszSnapshotDeviceObject)<< L";"
           << filterNullString(prop.m_pwszOriginatingMachine)<< L";" ;

答案 3 :(得分:2)

您可以使用辅助功能:

const wchar_t *SafeOutput(const wchar_t *str)
{
    return str ? str : L"null";
}
// Analogous function for ANSI strings
...
outstream << SafeOutput(prop.m_pwszOriginalVolumeName)   << L";"
          << SafeOutput(prop.m_pwszSnapshotDeviceObject) << L";"
          << SafeOutput(prop.m_pwszOriginatingMachine)   << L";"
          << ... // more strings here

答案 4 :(得分:2)

其他例子非常好。还有另一种选择,虽然我不推荐它(仅提及完整性)。

GCC有一个名为“带有省略操作数的条件”的扩展名,其基本上如下所示:

x = a ?: b;

与(与您的情况类似,请参见下文了解更多信息)相同:

x = a ? a : b;

不太便携。所以你可以写:

std::wstringstream outstream;
outstream << (prop.m_pwszOriginalVolumeName   ?: L"null") << L";"
          << (prop.m_pwszSnapshotDeviceObject ?: L"null") << L";"
          << (prop.m_pwszOriginatingMachine   ?: L"null") << L";"

但就像我说的那样,不会推荐这个,我会像其他答案一样使用帮助函数。

实际上有一种情况,它的表现与常规的三元不同,如果评估a有副作用。从页面:

  

在这个简单的例子中,省略中间操作数的能力不是   特别有用。当它变得有用时是第一个操作数   是,或可能(如果它是一个宏参数),包含副作用。然后   在中间重复操作数将执行副作用   两次。省略中间操作数使用已计算的值   没有重新计算它的不良后果。

请参阅http://gcc.gnu.org/onlinedocs/gcc/Conditionals.html