I need to compare one given value with a retrieved values. I do this several times in the code. I am not satisfied with how it looks and I am seeking for a some sort of an util
For your request to do
if (InSet(value)(GetValue1(), GetValue2(), GetValue3()))
{
// Do something here...
}
Try this:
template <typename T>
class InSetHelper
{
const T &Value;
void operator=(const InSetHelper &);
public:
InSetHelper(const T &value) : Value(value) {}
template<class Other, class Another>
bool operator()(const Other &value1, const Another &value2) const
{
return Value == value1 || Value == value2;
}
template<class Other, class Another, class AThird>
bool operator()(const Other &value1, const Another &value2, const AThird &value3) const
{
return Value == value1 || Value == value2 || Value == value3;
}
};
template <typename T>
InSetHelper<T> InSet(const T &value) { return InSetHelper<T>(value); }
This syntax might be more clear though:
if (MakeSet(GetValue1(), GetValue2(), GetValue3()).Contains(value))
{
// Do something here...
}
template <typename T, typename U, typename V>
class Set3
{
const T& V1;
const U& V2;
const V& V3;
void operator=(const Set3 &);
public:
Set3(const T &v1, const U &v2, const V &v3) : V1(v1), V2(v2), V3(v3) {}
template <typename W>
bool Contains(const W &v) const
{
return V1 == v || V2 == v || V3 == v;
}
};
template <typename T, typename U>
class Set2
{
// as above
};
template <typename T, typename U, typename V>
Set3<T, U, V> MakeSet(const T &v1, const U &v2, const V &v3)
{
return Set3<T, U, V>(v1, v2, v3);
}
template <typename T, typename U>
Set3<T, U> MakeSet(const T &v1, const U &v23)
{
return Set3<T, U, V>(v1, v2);
}
If those values are really part of a tree or a linked list, then you have your set/container already, and your best bet is to just use some recursion:
parent.ThisOrDescendantHasValue(value);
You'd just add this to whatever class parent and child belong to:
class Node
{
public:
Value GetValue();
Node *GetChild();
bool ThisOrDescendantHasValue(const Value &value)
{
return GetValue() == value
|| (GetChild() && GetChild->ThisOrDescendantHasValue(value));
}
};
How about using a boost::array (or std::tr1::array) and creating a simple function like this:
template <typename ValueType, size_t arraySize>
bool contains(const boost::array<ValueType, arraySize>& arr, const ValueType& val)
{
return std::find(arr.begin(), arr.end(), val)!=arr.end();
}
You could then reuse that pretty easily:
#include <string>
#include <iostream>
#include <boost\array.hpp>
template <typename ValueType, size_t arraySize>
bool contains(const boost::array<ValueType, arraySize>& arr, const ValueType& val)
{
return std::find(arr.begin(), arr.end(), val)!=arr.end();
}
int _tmain(int argc, _TCHAR* argv[])
{
boost::array<std::string, 3> arr = {"HI", "there", "world"};
std::cout << std::boolalpha
<< "arr contains HI: " << contains(arr, std::string("HI")) << std::endl
<< "arr contains blag: " << contains(arr, std::string("blag") ) << std::endl
<< "arr contains there: " << contains(arr, std::string("there") ) << std::endl;
return 0;
}
Edit: So boost is out. It's pretty easy to adapt this to a regular array:
template <typename ValueType, size_t arraySize>
bool contains(ValueType (&arr)[arraySize], const ValueType& val)
{
return std::find(&arr[0], &arr[arraySize], val)!=&arr[arraySize];
}
int _tmain(int argc, _TCHAR* argv[])
{
std::string arr[3] = {"HI", "there", "world"};
std::cout << std::boolalpha << "arr contains HI: " << contains(arr, std::string("HI")) << std::endl
<< "arr contains blag: " << contains(arr, std::string("blag") ) << std::endl
<< "arr contains there: " << contains(arr, std::string("there") ) << std::endl;
return 0;
}
std::find_first_of
.
Of course, if you only care about finding a single value, you can create your own wrapper around std::find
.
I would recommend your method 2, using a std::vector or other container and looking for membership. Since the order of elements that you're checking against is probably not relevant, you may want to use a std::set or std::map. If you have very many items in your set of values, then using a set or a map will be a faster, while if you have only a few a vector may be faster.
The advantage of any of these approaches is that you can then store the set/map somewhere common, and avoid having to build the set of matching responses every time.