Result should be const ? conditional operator : if then else

| 0 Comments

Simon says; I've stopped using ?: because it isn't as readable as an if .. then .. else. ...

I, personally, don't find the readability of the conditional operator (?:) a problem. No more than I find readability of assignments or pointer operations a problem. I can see how that since the conditional operator is only appropriate for use in certain circumstances, some programmers may not have come across it very often and for them it may be harder to understand than a construct that they know well.

In C++ I find that I use the conditional operator most often when the result is const as obviously I can't use the alternative if then else structure and still make the result const without resorting to a helper function to do the work....

So something like this;

   const DWORD dwServiceType = ownProcess ? SERVICE_WIN32_OWN_PROCESS : SERVICE_WIN32_SHARE_PROCESS;

rather than:

   DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
   
   if (!ownProcess)
   {
      dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
   }

Though you need to be careful. Sometimes it's best to use a helper function instead...

size_t BytesPerLine(
   const size_t lineLength)
{
   size_t bytesPerLine = 0;
   
   // useful comments about why?
   if (lineLength != 0)
   {
      bytesPerLine = (lineLength - 1)/3;
   }
   
   return bytesPerLine;
}
   
...
   
const size_t bytesPerLine = BytesPerLine(lineLength);

rather than:

   const size_t bytesPerLine = lineLength != 0 ? (lineLength - 1) / 3 : 0;

As I've said before, I'm keen on const so, for me, it's important not to make a variable non const just because you need a complex assignment for it.

Another place that the conditional operator is useful is in constructor initialisation lists; you simply can't replace it with an if then else so you're left with either the conditional operator or a helper function.

CAsyncSocketConnectionManager::CAsyncSocketConnectionManager(
   bool sslActive,
   CContext &sslContext,
   bool verifyPeer,
   IIOPool &pool,
   IAllocateAsyncSockets &socketAllocator,
   IAllocateBuffers &bufferAllocator)
   :  JetByteTools::Socket::CAsyncSocketConnectionManager(pool, socketAllocator, bufferAllocator, false),
      m_pContext(sslActive ? &sslContext : 0),             // <-----
      m_verifyPeer(verifyPeer),
      m_SSLConnectorIndex(socketAllocator.RequestUserDataSlot(_T("JeByteTools::OpenSSL::CAsyncSocketConnectionManager"))),
      m_bufferAllocator(bufferAllocator)
{
   
}

Or, perhaps, where boolean values need to be converted to enums or values of other types?

      PostIoOperation(pSocket, pBuffer, m_postZeroByteReads ? IO_Zero_Byte_Read_Request : IO_Read_Request);

and, of course, in log messages:

      LogMessage(_T("UserData") + (showUserData ? _T(": ") + ToString((int*)pUserData) : _T("")));

Like everything in programming, it depends. It's a useful construct, it can be misused but it can also be used to enhance the code that it's used in. I usually prefer not to nest conditional operators, but I have done it from time to time...

As for the main purpose of Simon's post, the C# ?? operator, it looks like syntactic sugar to me, but I'd be interested to see the 'nullable type' examples done with the conditional operator for comparison.

Leave a comment