3

I'm working with existing code that returns a reference, something like this:

int &func()
{
   static int i = 5;
   return i;
}

I would like to return an error case as "NULL" but of course NULL doesn't work in a return-by-reference function. If this were returning a pointer I might do this:

int *func()
{
   static int i = 5;

   if (!good)
       return NULL;
   else
       return &i;
}

Besides converting to a pointer-based return value, is there a best practice for returning a failure state?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
KJ7LNW
  • 1,437
  • 5
  • 11
  • 1
    References can't be `nullptr` - that's kind of the whole idea (mostly) of references vs pointers. So *no*. Also, don't use `NULL` in modern C++. – Jesper Juhl Aug 21 '23 at 19:37
  • 2
    You can also can kind of think of references as pointers that must point to a valid object. – Pepijn Kramer Aug 21 '23 at 19:38
  • 6
    Returning null or anything like it defeats about nine tenths of the point of references. Look into `std::optional` as an alternative. – user4581301 Aug 21 '23 at 19:40
  • 4
    Thinking about this a bit more, this might also be a good place to throw an exception. – user4581301 Aug 21 '23 at 19:41
  • @user4581301, I thought of that too...but the code isn't conducive to throwing at this point, for "reasons" – KJ7LNW Aug 21 '23 at 21:10
  • Not a worry. For all I know the failure case wouldn't be exceptional enough to be worth the overhead of exception handling. It's good low-hanging fruit to throw out there, though. – user4581301 Aug 21 '23 at 21:18

3 Answers3

6

yes, c++17 introduced std::optional, which can be empty, but it cannot have a reference so std::optional<<std::reference_wrapper<int>> is the proper "standard" return.

std::optional<<std::reference_wrapper<int>> func()
{

   static int i = 5;

   if (!good)
       return std::nullopt;  // return {}; works here
   else
       return i;
}

later c++20 introduced std::expected which can also return an Error Type to signal more information than just a "failure".

even if you are using older c++ standards you can still use optional in c++11 libraries, same as expected in c++11 libraries.


c++11 optional library can hold a reference, so you can use it for cleaner code.

tl::optional<int&> func()
{

   static int i = 5;

   if (!good)
       return tl::nullopt;  // return {}; works here
   else
       return i;
}
Ahmed AEK
  • 8,584
  • 2
  • 7
  • 23
2

std::optional<T> cannot take a reference type, so std::optional<int&> is invalid. I'd recommend returning a pointer here, and setting it to nullptr in the error case. It is Good and Valid C++ to return a non-owning pointer.

int* func()
{

   static int i = 5;

   if (!good)
       return nullptr;
   else
       return &i;
}
JohnFilleau
  • 4,045
  • 1
  • 15
  • 22
1

std::optional seems to be what you're looking for. See https://en.cppreference.com/w/cpp/utility/optional