Return empty std::pair from function
Solution 1
Generally speaking an empty pair doesn't even make sense. Afterall a pair
is per definition a container containing two objects.
You could however make something like an empty pair using Boost.Optional. Then you would either use a boost::optional<std::pair<...>>
giving you the option of returning either a pair or an empty state or use std::pair<boost::optional<...>, boost::optional<...>>
for a pair where either object could be empty.
Solution 2
You can returns pointer... Or use boost::optional<T>
. Optional will be better...
boost::optional<std::pair<int, int> > MyClass::someFunction()
{
return boost::optional<std::pair<int, int> >();
}
void f(const MyClass& f)
{
boost::optional<std::pair<int, int> > ret = f.someFunction();
if (!ret) // empty
{
...
}
}
Solution 3
The answer to your questions is easily explained by considering the way the C++ compiler generates code in this case.
The std::pair<int, int>
is returned-by-value.
Since MyClass::someFunction()
is returning an object by value, the sequence of events is as follows:
- The calling function reserves space on the stack for a
std::pair<int, int>
- The
MyClass::someFunction()
is called - The right hand side of the return statement is a assignment to the location reserved on the stack earlier. There is an implicit construction of a
std::pair<int, int>
taking place.
Thus returning a NULL pointer is impossible.
Solution 4
It wouldn't take much to create your own "optional pair" (similar to boost::optional<std::pair<…>>
, but with a different interface), e.g.:
template <typename T1, typename T2> struct OptPair : std::pair<T1, T2>
{
typedef std::pair<T1, T2> base_t;
bool contains;
OptPair() : contains(true) {}
explicit OptPair(bool x) : contains(x) {}
OptPair(const T1& x, const T2& y) : base_t(x, y), contains(true) {}
template <class U, class V>
OptPair(const std::pair<U,V> &p) : base_t(p), contains(true) {}
template <class U, class V> OptPair(const OptPair<U,V> &p) : base_t(p), contains(p.contains) {}
// No need to define operator=, as the default will construct an OptPair<T1, T2>
// if necessary, then copy members into *this.
};
template <typename T1, typename T2>
OptPair<T1, T2> makeOptPair() { return OptPair<T1, T2>(); }
template <typename T1, typename T2>
OptPair<T1, T2> makeOptPair(const T1 &x, const T2 &y) {
OptPair<T1, T2> p(true);
p.first = x;
p.second = y;
return p;
}
template <typename OS, typename T1, typename T2>
OS &operator<<(OS &os, const OptPair<T1, T2>& p) {
os << "<OptPair: ";
if (p.contains) os << p.first << ", " << p.second;
else os << "empty";
os << ">";
return os;
}
Then you can use it just like std::pair (and even use it interchangeably with std::pair, assigning values back and forth), but with the added ability to pass an "empty" value back like this:
OptPair<int, int> someFunction()
{
...
return OptPair<int, int>(false);
}
You have to make sure to check the result before using it, like this:
void doStuffWithPair(std::pair<int, int>);
void doStuffWithEmpty();
...
OptPair<int, int> ret = someFunction();
if (ret.contains) doStuffWithPair(ret);
else doStuffWithEmpty();
Solution 5
A pair, by definition, has 2 elements. It cannot have none.
You need something like boost::optional<std::pair<T1,T2>>
. Then you can choose to have a pair or not. You can find documentation for boost::optional here.
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on July 27, 2022Comments
-
Admin almost 2 years
Is it possible to return an empty pair from a function? Meaning, follow the rules of the function prototype, but do not have any elements in the pair (e.g. NULL). Understanding that a pair simply exists so I don't know if this is conceptually possible. I have a need to return a pair that is NULL or empty, if that makes any sense.
For example,
pair<int, int> MyClass::someFunction() { // do something that means we need to return an empty pair return NULL; // <--- this does not work obviously }
Unfortunately, boost is not a possibility for me.