将返回的迭代器强制转换为const

时间:2018-08-29 10:47:41

标签: c++ type-conversion const-iterator

我的代码中有以下for语句:

for (auto Iter = Target.begin(), 
        IterEnd = std::stable_partition(Target.begin(), Target.end(), Check);
    Iter != IterEnd; ++Iter)
    { /* loop statement */ }

重点是循环不会修改容器的元素,因此将迭代器声明为const_iterator是有意义的。对于第一个使用cbegin()来说,我可以轻松解决问题,但是第二个更为复杂。我不能在cbegin()中声明cend()stable_partition,因为当然stable_partition需要non const_iterators才能完成工作。

可能的解决方案是将auto替换为正确的类型,本例中为std::vector< std::string >::const_iterator。这会在第二次分配时强制从iterator转换为const_iterator

但是,我不喜欢它。类型很容易迅速变得难以管理,因此我正在寻找一种解决方案,使我可以使用auto,而无需在循环外声明一些怪异的东西。有什么建议吗?

2 个答案:

答案 0 :(得分:2)

我认为最清晰的解决方案是将std::stable_partition放在for之前。这将产生等效的算法。

问题是stable_partition返回了可以修改元素的迭代器。幸运的是,从container::iteratorcontainer::const_iterator有一个隐式转换(对于大多数标准容器)。要进行转换,您可以使用IterEndstd::vector<T::const_iterator或我的个人喜好指定decltyp(Target.cbegin()的类型:

auto Iter = Target.cbegin();
decltype(Iter) IterEnd = std::stable_partition(Target.begin(), Target.end(), Check);

for (; Iter != IterEnd; ++Iter)
{
}

为完整起见,您可以根据需要将所有内容保留在for内,但我认为它不太可读:

for (auto Iter = Target.cbegin(),
        IterEnd = (decltype(Iter)) std::stable_partition(Target.begin(), Target.end(), Check);
     Iter != IterEnd;
     ++Iter)
{}

答案 1 :(得分:0)

这是通过功能界面表达想法的一种方法:

#include <vector>
#include <algorithm>
#include <iostream>

namespace detail {
    template<class Container, class F>
    struct const_partitioned_target
    {
        using container_type = std::decay_t<Container>;
        using const_iterator = typename container_type::const_iterator;

        const_partitioned_target(Container& cont, F f)
            : first(cont.cbegin())
            , last(std::partition(cont.begin(), cont.end(), f))
        {

        }

        const_iterator begin() const { return first; }

        const_iterator end() const { return last; }

        const_iterator first, last;
    };
}

template<class Container, class F>
auto const_partitioned_target(Container& cont, F&& f)
{
    return detail::const_partitioned_target<Container, std::decay_t<F>>(cont, std::forward<F>(f));
};

int main()
{
    std::vector<int> Target { 1, 2, 6, 9, 10, 20, 30, 40 };

    auto Check = [](auto&& x)
    {
        return x < 10;
    };

    for(auto&& elem : const_partitioned_target(Target, Check))
    {
        // elem will have the type: int const&
        std::cout << elem << '\n';
    }
}

预期输出:

1
2
6
9