Is there a shorter way of writing `StringPtr ? StringPtr : "null"`?
I have this code:
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
Is there a way to avoid code duplication and still have concise code?
You could define a small function:
whatever_t strOrNull(whatever_t str) {
return str ? str : L"null";
}
Then your code becomes
std::wstringstream outstream;
outstream << strOrNull(prop.m_pwszOriginalVolumeName) << L";"
<< strOrNull(prop.m_pwszSnapshotDeviceObject) << L";"
<< strOrNull(prop.m_pwszOriginatingMachine) << L";"
<< ... // some more strings here
Or if you wanted to be even more concise, you could do this (depending on what whatever_t
is; if wstringstream
already has an operator<<
overload for that type, this won't work):
wstringstream& operator<<(wstringstream& out, whatever_t str) {
if (str)
out << str;
else
out << L"null";
return out;
}
Then your code becomes
std::wstringstream outstream;
outstream << prop.m_pwszOriginalVolumeName << L";"
<< prop.m_pwszSnapshotDeviceObject << L";"
<< prop.m_pwszOriginatingMachine << L";"
<< ... // some more strings here
A function, or a lambda:
auto foo = [](const wchar * p) { return p ? p : L"null;" };
outstream << foo(prop.m_pwszOriginalVolumeName) << L";"
<< foo(prop.m_pwszSnapshotDeviceObject) << L";"
<< ...etc...
The other examples are really good. There is another option, though I wouldn't recommend it (only mentioning for completeness).
GCC has an extension called "Conditionals with Omitted Operands" Which basically looks like this:
x = a ?: b;
which is the same as (in simple cases like yours, see below for more info):
x = a ? a : b;
Just less portable. So you could write:
std::wstringstream outstream;
outstream << (prop.m_pwszOriginalVolumeName ?: L"null") << L";"
<< (prop.m_pwszSnapshotDeviceObject ?: L"null") << L";"
<< (prop.m_pwszOriginatingMachine ?: L"null") << L";"
But like I said, I would not recommend this, I would use a helper function like the other answers mention.
There actually is a case where it performs differently than a regular ternary if, and that's if evaluating a
has side effects. From the page:
In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, or may (if it is a macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the value already computed without the undesirable effects of recomputing it.
See http://gcc.gnu.org/onlinedocs/gcc/Conditionals.html
A simple function should do the trick.
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";" ;
You could use a helper function:
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
精彩评论