Recursive templates are still quite confusing to me, and I don't feel like I'm using them as well as I should be. For example, I tried to use recursive templates to write a function that will remove all duplicate members of an n-dimensional vector, and I believe that I have some code that works. However, I'm almost confident that there's a better way to do this:
template <typename T>
void remove_if_duplicate(std::vector<T>& vec, bool at_end)
{
static std::set<T> seen;
if(!at_end)
{
auto newEnd = std::remove_if(vec.begin(), vec.end(), [=](const T& value)
{
if(seen.find(value) != std::end(seen))
return true;
seen.insert(value);
return false;
});
vec.erase(newEnd, vec.end());
std::cout << "\n\nhere: " << at_end << "\n\n";
}
if(at_end) {seen.clear();}
}
template <typename T>
void remove_if_duplicate(std::vector<std::vector<T>>& v, bool at_end)
{
if(!at_end)
{
for(unsigned int i = 0; i < v.size(); i++)
{
remove_if_duplicate(v[i], at_end);
}
}
if(at_end) {remove_if_duplicate(v[0], at_end);}
}
template <typename T>
void remove_duplicates(std::vector<std::vector<T>>& v)
{
remove_if_duplicate(v, false);
remove_if_duplicate(v, true);
}
See an example here: http://ift.tt/2v80T10
Notice how I declare the set variable "seen" as a static variable of the base function. I have do this so that I still have access to previous items that I have "seen" before even when iterating through multidimensional vectors. I cannot declare the "seen" variable inside the second function because the base type that the multidimensional vectors is templated on is unknown at that point (and then the case of a single-dimensional vector wouldn't work either). So then I have to pass booleans into these functions in order to decide when to actually clear the static set variable so that I can use this function again for other n-dimensional vectors.
While it seems to work so far and is giving me the behavior I want, I'm not sure if any unexpected bugs will appear as a result of my poor implementation. I think that the way that I have done this here is far from ideal, and I'm sure there's a better, more efficient way. How would you do it differently?
Aucun commentaire:
Enregistrer un commentaire