递归模板对我来说仍然很混乱,我觉得我并不像我应该那样使用它们。例如,我尝试使用递归模板来编写一个函数,该函数将删除n维向量的所有重复成员,我相信我有一些有效的代码。但是,我几乎相信有更好的方法可以做到这一点:
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);
}
请在此处查看示例:http://coliru.stacked-crooked.com/a/6e11f9ababcdfa12
注意我如何声明set变量&#34; see&#34;作为基函数的静态变量。我已经这样做了,所以我仍然可以访问我以前的所有项目&#34;看到&#34;甚至在迭代多维向量之前。我无法宣布&#34;见过&#34;第二个函数内部的变量,因为多维向量被模板化的基本类型在那一点是未知的(然后单维向量的情况也不会起作用)。那么我必须将布尔值传递给这些函数,以便决定何时实际清除静态集变量,以便我可以再次将此函数用于其他n维向量。
虽然它似乎工作到目前为止并且正在给我我想要的行为,但我不确定是否会因为我的执行不佳而出现任何意外错误。我认为我在这里做到这一点的方式远非理想,我确信这是一种更好,更有效的方法。 你会如何区别?
答案 0 :(得分:2)
您可以通过使用辅助类来构建正确的set
来消除静态:
template <typename T> struct inner_type
{
using type = T;
};
template <typename T> struct inner_type<std::vector<T>>
{
using type = typename inner_type<T>::type;
};
然后你可以这样做:
template <typename T>
void RemoveDuplicatesImpl(std::vector<T>& v,
std::set<T>& values)
{
v.erase(std::remove_if(v.begin(), v.end(), [&](const T& t)
{
return !values.insert(t).second;
}), v.end());
}
template <typename T>
void RemoveDuplicatesImpl(std::vector<std::vector<T>>& v,
std::set<typename inner_type<T>::type>& values)
{
for (auto& inner : v) {
RemoveDuplicatesImpl(inner, values);
}
}
template <typename T>
void RemoveDuplicates(std::vector<T>& v)
{
std::set<typename inner_type<T>::type> values;
RemoveDuplicatesImpl(v, values);
}
答案 1 :(得分:0)
我根本不会使用套装。由于您使用的是std::set
,因此结果向量中元素的顺序无关紧要。
template<class T> void RemoveDuplicates(std::vector<T> &v)
{
std::sort(v.begin(), v.end());
v.erase(v.begin(), std::unique(v.begin(), v.end());
}
template<class T> void RemoveDuplicates(std::vector<std::vector<T> > &v)
{
// remove duplicates from every individual vector
for (auto &i : v) RemoveDuplicates(e);
// for every vector, remove any copy of its elements in subsequent vectors
auto i = v.begin();
auto end = v.end();
while (i != end)
{
auto next = std::advance(i, 1); // alternatively next = i+1
auto next_i = next;
while (next != end)
{
for (const auto &e : *i)
next->erase(next->begin(), std::remove(next->begin(), next->end(), e));
next = std::advance(next, 1); // alternatively ++next
}
i = next_i;
}
}