Je pense que c'est un bon cas d'utilisation pour boost::optional
(std: : en c++17).
Vous n'avez pas vraiment envie de générer ou de traiter une exception, car le fait que l'élément ne figure pas sur la carte ne constitue pas une circonstance exceptionnelle.
Je pense que je l'exprimerais comme ça :
int myIndex = 1;
foo(maybe_at(myMap, myIndex).value_or_eval([]()->Something& {
// perform error code here
return default_something;
}));
Exemple de code complet ici :
#include <map>
#include <type_traits>
#include <boost/optional.hpp>
template<class Container>
struct container_traits
{
using maybe_const_type = std::remove_reference_t<Container>;
using container_type = std::decay_t<Container>;
using is_const = std::is_const<maybe_const_type>;
using key_type = typename container_type::key_type;
using raw_mapped_type = typename container_type::mapped_type;
using mapped_type = std::conditional_t<is_const::value, std::add_const_t<raw_mapped_type>, raw_mapped_type>;
using mapped_reference = std::add_lvalue_reference_t<mapped_type >;
};
template<class Container, class Key>
auto maybe_at(Container&& container, Key&& key)
{
using traits = container_traits<Container>;
using result_type = boost::optional<typename traits::mapped_reference>;
auto result = result_type {};
auto ifind = container.find(key);
if (ifind != container.end()) {
result = ifind->second;
}
return result;
}
struct Something {};
void foo(Something&) {}
void foo(const Something&) {}
std::map<int, Something> myMap1;
const std::map<int, Something> myMap2;
auto default_something = Something{};
int main() {
int myIndex = 1;
foo(maybe_at(myMap1, myIndex).value_or_eval([]()->Something& {
// perform error code here
return default_something;
}));
foo(maybe_at(myMap2, myIndex).value_or_eval([]()->Something const& {
// perform error code here
return default_something;
}));
}