可分配对左值和右值的引用

时间:2016-07-12 21:54:21

标签: c++ c++11

假设我有一个函数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,因为它不能构建临时工具。

我有哪些替代方案?

1 个答案:

答案 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));
}