c++ - 对左值和右值的可分配引用

标签 c++ c++11

假设我有一个函数 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因为我不想修改原来的容器,但我也不想做无谓的复制。最简单的解决方案是创建一个指针 vector ,但问题是 *first可能返回 const T& (例如,来自 vector )或 T (例如,来自流)。

/* ??? */因此 part 在概念上应该等同于 const T& .我们真的不能这样做,因为 vector s 不能包含不可分配的引用。我们不能使用 reference_wrapper<const T>要么,因为它不能从临时构造。

我有什么选择?

最佳答案

你想要 /* ??? */ 是一个可能拥有也可能不拥有 T 对象的类型,这取决于它是用临时 T 还是 const 构造的T&。出于显而易见的原因,通常应避免此类类型。

一种替代方法是使用标签分派(dispatch)或 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));
}

关于c++ - 对左值和右值的可分配引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38339471/

相关文章:

c++ - QGraphicsWidget的鼠标拖动。

c++ - 在匿名命名空间中使用命名空间安全吗?

c++ - 用于在C++中表示JSON的数据类型

algorithm - 为什么我们应该在 <algorithm> 头的函数之前使用 std 命名空间而不应该在 <cmath> 头的函数之前使用它?

c++ - 在基于范围的 for 循环中使用转发引用有什么好处?

c++ - 递归和常量变量

c++ - 尝试将函数作为参数传递时未解析的重载函数类型

c++ - 为什么 std::atomic 中的所有成员函数都带有和不带有 volatile?

c++ - C++对象构造方法的区别

c++ - 使用自动变量打印 vector 的内容