Reputation: 34597
I have a method which takes const ref to a set. I want to call it and m.b. pass a set to it. If I have it. So first I see if I have a set:
const auto& it = mapOfSets.find("token");
if (it != std::end(mapOfSets)) {
myFunction(it.second);
} else {
MySetType emptySet;
myFunction(emptySet);
}
What is an idiomatic way of doing this? I don't like the above because call to myFunction is repeated twice and there is a few other arguments, so there is some unnecessary code duplication.
The C programmer in me just wants to change the function to accept a pointer and pass nullptr if set is not found, but i feel that C++ is all about avoiding pointers now?..
Upvotes: 2
Views: 541
Reputation: 2748
Maybe a handwritten optional_reference
that can reference nullptr
but will throw
when dereferencing it and has no additional bool
#include <stdexcept>
#include <memory>
class null_access_exception: public std::logic_error
{
using base = std::logic_error;
public:
null_access_exception():
base("Try to dereference null optional_reference!")
{}
};
template <class Ptr_t>
class optional_reference
{
using self = optional_reference;
using reference = decltype(*std::declval<Ptr_t>());
Ptr_t ptr = nullptr;
public:
optional_reference() = default;
optional_reference(const self&) = default;
self& operator = (const self&) = delete;
template <class U>
constexpr optional_reference(U &&obj) noexcept:
ptr(std::addressof(obj))
{}
constexpr explicit operator bool() const noexcept
{ return has_value(); }
constexpr bool has_value() const noexcept
{ return ptr != nullptr; }
constexpr auto& value() const
{
if (!has_value())
throw null_access_exception();
return *ptr;
}
template <class U>
constexpr auto& value_or(U &&obj) const noexcept
{
if (has_value())
return *ptr;
else
return reference(std::forward<U>(obj));
}
};
and then
Change myfunction
so that it accept optional_reference
and then check it.
Wrap it like below.
constexpr const static auto null_set(); void Myfunction(optional_wrapper ref) { myfunction(ref.value_or(null_set)); }
Upvotes: 0
Reputation: 15334
If you write a helper function to find a set in the map then you can return a reference to a special empty set in the case that you did not find anything:
const MySetType& find(const MyMapType& mapOfSets, const std::string& key) {
auto it = mapOfSets.find(key);
if (it != std::end(mapOfSets)) {
return it->second;
}
static const MySetType emptySet;
return emptySet;
}
Then your calling code is simply:
myFunction(find(mapOfSets, "token"));
Upvotes: 1
Reputation: 49028
You can use the conditional operator:
myFunction(it != mapOfSets.end() ? it->second : MySetType{});
I don't think there is an idiomatic way though.
Upvotes: 3