假设我有一个函数def get_form_class(self):
return self.request.user.organization.forms.CreateUserForm
,它可以计算任何未排序范围内的唯一元素的数量:
unique_count
我创建了一个新的template<typename InputIt>
std::size_t unique_count(InputIt first, InputIt last)
{
using T = typename std::iterator_traits<InputIt>::value_type;
std::vector</* ??? */> v(first, last);
std::sort(v.begin(), v.end());
return std::distance(v.begin(),
std::unique(v.begin(), v.end()));
}
,因为我不想修改原始容器,但我也不想进行不必要的复制。最简单的解决方案是创建指针向量,但问题是vector
可能返回*first
(例如,来自const T&
)或vector
(例如,从一个流)。
T
部分因此在概念上应与/* ??? */
等效。我们无法真正做到这一点,因为const T&
无法保存无法分配的引用。我们也不能使用vector
,因为它不能构建临时工具。
我有哪些替代方案?
答案 0 :(得分:2)
您希望/* ??? */
成为可能拥有或不拥有T
对象的类型,具体取决于它是使用临时T
还是const T&
构建的。出于显而易见的原因,通常应避免使用此类型。
一种替代方法是使用标记分派或SFINAE来选择两种可能的实现之一,具体取决于*first
是返回引用还是非引用类型。
另一种方法是缩小算法范围,使其只接受前向迭代器。在这里,您可以保证能够简单地存储迭代器并使用它们来比较指向的元素:
template <typename ForwardIt>
std::size_t unique_count(ForwardIt first, ForwardIt last) {
std::vector<ForwardIt> v;
for (auto i = first; i != last; ++i) {
v.push_back(i);
}
const auto pred = [](ForwardIt a, ForwardIt b) { return *a < *b; };
std::sort(v.begin(), v.end(), pred);
return std::distance(v.begin(), std::unique(v.begin(), v.end(), pred));
}