如何实现const_auto,因为c++ 11缺少它

How does one achieve const_auto, since C++11 lacks it?

本文关键字:c++ 因为 auto 何实现 实现 const      更新时间:2023-10-16

c++ 11的auto类型很方便,所以现在人们也想要一个const_auto类型。例如,假设std::list<T> a;,如果

auto p = a.begin();

具有类型std::list<T>::iterator,则希望

const_auto p = a.begin();

的类型为std::list<T>::const_iterator。不幸的是,c++ 11似乎没有听说过const_auto。因此,一个人如何才能以好的风格达到预期的效果呢?

c++ 11允许你写

const auto p = a.begin();

然而,这并不是你想要的。这使得一个常规迭代器指向不能更改值的非常量数据。

右边a.begin()的类型是由a的类型决定的,而不是由左边的任何东西决定的。如果a是非const,则调用a.begin()的非const版本。因此,您可以将a强制转换为const&然后使用它,或者你可以给a做一个常量引用并使用它:

const auto& b = a;
auto p = b.begin();
但是,更简单的方法是使用新引入的.cbegin()和.cend():
auto p = a.cbegin();

我经常发现将实例转换为其类型的const版本很有用,但我发现使用const_cast用于此目的是庸俗的(保留删除 const,现在搜索它会发现危险的代码),而且它过于冗长(重复完整的类型?嗨!)

因此这个片段:

template<typename T>
T const& as_const( T& t ) { return t; }

,然后你可以用它来解决你的问题,如下所示:

auto p = as_const(a).begin();

我认为这是很好的自我记录。

c++ 11中有STL容器和C数组的函数模板。参见std::begin()std::end()。不幸的是,由于某些原因,没有等效的std::cbegin()std::cend()

你可以使用这些函数来做你想做的事情:

template<class T, size_t N>
T const * cbegin(T(&a)[N])
{
    return &a[0];
}
template<class T, size_t N>
T const * cend(T(&a)[N])
{
    return &a[N];
}
template<class T>
typename T::const_iterator cbegin(T const & container)
{
    return container.cbegin();
}
template<class T>
typename T::const_iterator cend(T const & container)
{
    return container.cend();
}

后两个也可以声明为:

template<class T>
auto cbegin(T const & container) -> decltype(container.cbegin())
{
    return container.cbegin();
}
template<class T>
auto cend(T const & container) -> decltype(container.cend())
{
    return container.cend();
}

你可以这样做:

char x[] = "ab";
auto b = cbegin(x);
auto e = cend(x);
相关文章: