给定cbegin(),cend(),为什么没有cfront(),cback(),cfind(),...?

时间:2015-05-26 10:13:55

标签: c++ stl c++14

所以,为了允许代码如

auto vect = ...;
auto it = vect.begin(), end = vect.end(); // want const_iterator, getting iterator

选择begin()end()的正确重载,即使对于非const容器,也会添加更明确的cbegin() / cend()函数。

为什么要停在那里?

关联容器的find()方法具有相同的问题。序列容器有front()back(),同样存在同样的问题。

这些遗漏的显式const版本是遗漏还是设计?

2 个答案:

答案 0 :(得分:7)

更广泛的API需要花费成本,甚至只是在寻找您想要的功能时跳过它。

template<class T>
T const as_const(T&& t) noexcept(noexcept(T(std::declval<T>())) {
  return std::forward<T>(t);
}
template<class T>
T const& as_const(T& t) noexcept {
  return t;
}

完成你想要的大部分工作。它甚至会使cbegin过时。

(根据以下@ T.C提供的n4380对上述代码进行了修改。代码不同,因为我认为n4380在T&&情况下略有错误。)

答案 1 :(得分:3)

cbegin / cend的目的是解决特定问题。请考虑以下代码:

std::vector<int> & v = //... v is a non-const reference

// For clarity, I want this iterator to be a const_iterator.
// This works because iterator is implicitly convertible to const_iterator
std::vector<int>::const_iterator iter = find(v.begin(),v.end(),42);

// (1) Now I want to use iter in an algorithm
std::find(iter, v.end(), 38); //Error, can not deduce the template parameter for Iter. 

// (2) This works
std::find(iter, const_cast<const std::vector<int> &>(v).end(), 38);

// (3) This is the same as (2).
std::find(iter, v.cend(), 38);

问题在于,由于模板推导规则的工作原理,编译器无法在语句(1)中推导出模板迭代器参数,因为Container::iteratorContainer::const_iterator(可能)完全是两个不相关的类型(即使前者在后者中可以隐式转换)。

声明(2)并不完美,这就是我们需要 cend()的原因。

现在,front()back() et similia都会返回引用。非const引用总是可以在模板化函数中推导为const,即:

template<class T> void f( const T & l, const T & r);

int main()
{
    int x; vector<int> v;

    //This will works even if the return type of front() is int&.
    f(x, v.front());
 }

由于标准要求Container::const_reference等于const Container::value_type &cfront() / cback()不会向我们购买任何东西。

值得一提的是,其他容器库(看着你Qt)是使用Copy-On-Write实现的。

这意味着在这样的容器上调用const函数可能比调用等效的非const版本便宜得多,因为非const可能会复制整个容器。

因此,Qt容器的界面中有很多constFunction,用户可以自由选择正确的。{/ p>

相关问题