STL算法中的begin(),end()烦恼

时间:2009-03-29 11:22:33

标签: c++ algorithm stl

我喜欢STL算法,更喜欢使用算法而不是通常的循环 几乎所有STL算法通常用作:

std::algorithm_name( container.begin(), container.end(), ..... )  

container.begin(), container.end() - 是我项目中最受欢迎的单词对之一。

有人有同样的问题吗? 你们是怎么解决这个问题的? 您有什么建议可以避免这种重复?我看到了一些解决方法,但它们都有不同的限制(宏使用,与通常的指针不兼容等)。

8 个答案:

答案 0 :(得分:28)

下一个C ++标准,C ++ 0X(其中X代表,希望是9)将增加从迭代器角度转换到容器角度的可能性。你将能够做到例如。

  

的std ::排序(my_vec);

如果您不能等待,我建议您查看:Boost.Range

如果您对迭代器/范围非常感兴趣,我建议您阅读Andrei的“ iterators must go

答案 1 :(得分:19)

许多人遇到了这种麻烦。虽然迭代器概念非常普遍,但缺乏一些可用性。

输入'范围'概念。最好避免任何代码重复。因此,如果您在整个代码中遇到.begin()和.end(),那么最好在'iterator-getting'和实际算法之间创建一个层。

参考文献:

...

答案 2 :(得分:7)

#define ALL(x) (x).begin(), (x).end()

sort(ALL(vec));

答案 3 :(得分:3)

C++11已经解决了语言中的这种轻微烦恼。

答案 4 :(得分:3)

首先,我认为这不是一个大问题。一般来说,我真的不在乎输入更多的字符。可读性更重要,我认为开始/结束是完全可读的。

较短的容器名称可以提供帮助(con.begin()比container.begin()更容易输入)

传递迭代器而不是容器本身意味着在任何情况下都不必多次调用begin / end。

这不是困扰我的事情。

答案 5 :(得分:3)

如果非常糟糕,我可能会为新命名空间中最常用的算法创建一堆模板:

namespace my_ranged_algorithms {
    // Metafunction for extracting an appropriate iterator from
    // the container type
    template <typename T>
    struct get_iterator_type_for;

    // For vectors
    template <typename T>
    struct get_iterator_type_for<std::vector<T> > {
        typedef typename std::vector<T>::iterator type;
    };

    template <typename T>
    struct get_iterator_type_for<std::vector<T> const> {
        typedef typename std::vector<T>::const_iterator type;
    };

    // For C arrays
    template <typename T, size_t N>
    struct get_iterator_type_for<T(&)[N]> {
        typedef T* type;
    };

    // Generic begin() and end() wrappers

    // For all standard containers        
    template <typename Cont>
    typename get_iterator_type_for<Cont>::type begin(Cont& c) {
        return c.begin();
    }

    template <typename Cont>
    typename get_iterator_type_for<Cont>::type end(Cont& c) {
        return c.end();
    }

    // For C arrays
    template <typename T, size_t N>
    typename get_iterator_type_for<T (&)[N]>::type begin(T (&c)[N]) {
        return c;
    }

    template <typename T, size_t N>
    typename get_iterator_type_for<T (&)[N]>::type end(T (&c)[N]) {
        return c + N;
    }

    // Finally, the actual algorithm wrappers

    // copy
    template <typename Cont, typename OutIter>
    OutIter copy(Cont& from, OutIter to) {
        return std::copy(begin(from), end(from), to);
    }

    // remove
    template <typename Cont, typename T>
    typename get_iterator_type_for<Cont>::type remove(Cont& from, T x) {
        return std::remove(begin(from), end(from), x);
    }

    // etc.
};

然后像这样打电话给他们:

vector<int> a, b;
using namespace my_ranged_algorithms;

copy(a, back_inserter(b));
b.erase(remove(b, 42), b.end()); // Remember to call erase() after remove()!

答案 6 :(得分:3)

This nice presentation [PDF]关于可能的未来解决方案最近与reddit相关联。它讨论了如何使用范围概念完全替换迭代器。

答案 7 :(得分:1)

boost :: range_ex将在c ++ 0x之前解决这个问题。

在此期间自己写几个包装并不难。