Add a generic contains() function...

...that detects if a container contains a given value.

This will use std::find in most cases, but uses the member find()
function when detecting if an associative container contains a
key_value. So it should be efficient, while allowing more readable
code.

This function is in the util:: namespace to avoid any future naming
conflicts.
This commit is contained in:
J. Tyne 2013-02-08 15:34:52 +00:00
parent 43018403fe
commit 793d19b3a8
3 changed files with 49 additions and 39 deletions

View file

@ -619,22 +619,6 @@ std::string find_recall_location(const int side, map_location& recall_location,
}
namespace { // Helpers for check_recruit_location()
/// Returns whether or not the value is found in the vector.
template<typename T>
inline bool contains(const std::vector<T> & container, const T & value)
{
typename std::vector<T>::const_iterator end = container.end();
return std::find(container.begin(), end, value) != end;
}
/// Returns whether or not the value is found in the set.
template<typename T>
inline bool contains(const std::set<T> & container, const T & value)
{
return container.find(value) != container.end();
}
/**
* Checks if @a recruiter can recruit at @a preferred.
* If @a unit_type is not empty, it must be in the unit-specific recruit list.
@ -652,7 +636,7 @@ namespace { // Helpers for check_recruit_location()
if ( !unit_type.empty() ) {
// Make sure the specified type is in the unit's recruit list.
if ( !contains(recruiter.recruits(), unit_type) )
if ( !util::contains(recruiter.recruits(), unit_type) )
return RECRUIT_NO_ABLE_LEADER;
}
@ -691,7 +675,7 @@ RECRUIT_CHECK check_recruit_location(const int side, map_location &recruit_locat
// If the specified unit type is in the team's recruit list, there is no
// need to check each leader's list.
if ( contains((*resources::teams)[side-1].recruits(), unit_type) )
if ( util::contains((*resources::teams)[side-1].recruits(), unit_type) )
check_type.clear();
// If the check location is not valid, we will never get an "OK" result.

View file

@ -51,15 +51,6 @@ void copy_keys(config& out,
}
}
}
//helper function
inline bool contains(const std::vector<std::string>& container,
const std::string& value)
{
return std::find(container.begin(), container.end(), value)
!= container.end();
}
} //anonymous namespace
namespace mp
@ -190,7 +181,7 @@ std::vector<std::string> manager::get_required_not_enabled(const elem& e) const
std::vector<std::string> result;
BOOST_FOREACH (std::string str, required) {
if (!contains(mods_, str)) {
if ( !util::contains(mods_, str) ) {
result.push_back(str);
}
}
@ -231,7 +222,7 @@ bool manager::conflicts(const elem& elem1, const elem& elem2, bool directonly) c
std::vector<std::string> ignored =
utils::split(data1["ignore_incompatible_" + elem2.type]);
if (contains(ignored, elem2.id)) {
if ( util::contains(ignored, elem2.id) ) {
return false;
}
}
@ -240,7 +231,7 @@ bool manager::conflicts(const elem& elem1, const elem& elem2, bool directonly) c
std::vector<std::string> ignored =
utils::split(data2["ignore_incompatible_" + elem1.type]);
if (contains(ignored, elem1.id)) {
if ( util::contains(ignored, elem1.id) ) {
return false;
}
}
@ -252,24 +243,24 @@ bool manager::conflicts(const elem& elem1, const elem& elem2, bool directonly) c
std::vector<std::string> allowed =
utils::split(data1["allow_" + elem2.type]);
result = !contains(allowed, elem2.id) && !requires(elem1, elem2);
result = !util::contains(allowed, elem2.id) && !requires(elem1, elem2);
} else if (data1.has_attribute("disallow_" + elem2.type)) {
std::vector<std::string> disallowed =
utils::split(data1["disallow_" + elem2.type]);
result = contains(disallowed, elem2.id);
result = util::contains(disallowed, elem2.id);
}
if (data2.has_attribute("allow_" + elem1.type)) {
std::vector<std::string> allowed =
utils::split(data2["allow_" + elem1.type]);
result = result || (!contains(allowed, elem1.id) && !requires(elem2, elem1));
result = result || (!util::contains(allowed, elem1.id) && !requires(elem2, elem1));
} else if (data2.has_attribute("disallow_" + elem1.type)) {
std::vector<std::string> disallowed =
utils::split(data2["disallow_" + elem1.type]);
result = result || contains(disallowed, elem1.id);
result = result || util::contains(disallowed, elem1.id);
}
if (result) {
@ -326,7 +317,7 @@ bool manager::requires(const elem& elem1, const elem& elem2) const
std::vector<std::string> required =
utils::split(data["force_modification"]);
return contains(required, elem2.id);
return util::contains(required, elem2.id);
}
return false;
@ -523,7 +514,7 @@ bool manager::change_scenario(const std::string& id)
std::vector<std::string> newmods = req;
BOOST_FOREACH (const std::string& i, mods_) {
if (!contains(con, i)) {
if ( !util::contains(con, i) ) {
newmods.push_back(i);
}
}
@ -593,7 +584,7 @@ bool manager::change_era(const std::string& id)
std::vector<std::string> newmods = req;
BOOST_FOREACH (const std::string& i, mods_) {
if (!contains(con, i)) {
if ( !util::contains(con, i) ) {
newmods.push_back(i);
}
}
@ -666,7 +657,7 @@ bool manager::change_modifications
}
}
if (!contains(compatible, era_)) {
if ( !util::contains(compatible, era_) ) {
if (!compatible.empty()) {
era_ = change_era_dialog(compatible);
} else {
@ -703,7 +694,7 @@ bool manager::change_modifications
}
}
if (!contains(compatible, scenario_)) {
if ( !util::contains(compatible, scenario_) ) {
if (!compatible.empty()) {
scenario_ = change_scenario_dialog(compatible);
} else {

View file

@ -241,8 +241,43 @@ public:
T &operator*() const { return *ptr_; }
};
namespace detail {
/// A struct that exists to implement a generic wrapper for std::find.
/// Container should "look like" an STL container of Values.
template<typename Container, typename Value> struct contains_impl {
static bool eval(const Container & container, const Value & value)
{
typename Container::const_iterator end = container.end();
return std::find(container.begin(), end, value) != end;
}
};
/// A struct that exists to implement a generic wrapper for the find()
/// member of associative containers.
/// Container should "look like" an STL associative container.
template<typename Container>
struct contains_impl<Container, typename Container::key_type> {
static bool eval(const Container & container,
const typename Container::key_type & value)
{
return container.find(value) != container.end();
}
};
}//namespace detail
/// Returns true iff @a value is found in @a container.
/// This should work whenever Container "looks like" an STL container of Values.
/// Normally this uses std::find(), but a simulated partial template specialization
/// exists when Value is Container::key_type. In this case, Container is assumed
/// an associative container, and the member function find() is used.
template<typename Container, typename Value>
inline bool contains(const Container & container, const Value & value)
{
return detail::contains_impl<Container, Value>::eval(container, value);
}
}//namespace util
#if 1
# include <SDL_types.h>
typedef Sint32 fixed_t;