“Generic” iterator in c++

后端 未结 7 1211
慢半拍i
慢半拍i 2021-01-04 06:09

I have:

void add_all_msgs(std::deque::iterator &iter);

How can I make that function \"generic\", so it can take any kind

相关标签:
7条回答
  • 2021-01-04 06:51

    Slightly simpler that the above (in that it leverages existing libraries):

    #include <boost/static_assert.hpp> // or use C++0x static_assert
    #include <boost/type_traits/is_same.hpp>
    
    template <typename InputIterator>
    void add_all_msgs( InputIterator it ) {
        BOOST_STATIC_ASSERT(( boost::is_same<
            typename std::iterator_traits<InputIterator>::value_type,
            Message>::value ));
        // ...
    
    0 讨论(0)
  • 2021-01-04 06:59
    #include <deque>
    #include <vector>
    #include <list>
    #include <string>
    using namespace std;
    
    template<typename T>
    void add_all_msgs(T &iter)
    {
    
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        std::deque<string>::iterator it1;
        std::vector<string>::iterator it2;
        std::list<string>::iterator it3;
    
        add_all_msgs(it1);
        add_all_msgs(it2);
        add_all_msgs(it3);
    
    
        return 0;
    }
    
    0 讨论(0)
  • 2021-01-04 07:00
    template <typename Iterator>
    void add_all_messages(Iterator first, Iterator last)
    

    usage :

    vector<message> v;
    add_all_messages(v.begin(), v.end());
    

    You need to specify the end, otherwise you won't know when to stop! It also gives you the flexibility of adding only a subrange of a container.

    0 讨论(0)
  • 2021-01-04 07:04

    It's difficult to have dynamic polymorphism with C++-style iterators. operator++(int) returns by value, which afaik is intractable: you can't have a virtual member function which returns *this by value without it being sliced.

    If possible, I recommend using templates as everyone else says.

    However if you do need dynamic polymorphism, for example because you can't expose the implementation of add_all_msgs as a template would do, then I think you could pretend to be Java, like this:

    struct MessageIterator {
        virtual Message &get() = 0;
        virtual void next() = 0;
        // add more functions if you need more than a Forward Iterator.
        virtual ~MessageIterator() { };  // Not currently needed, but best be safe
    };
    
    // implementation elsewhere. Uses get() and next() instead of * and ++
    void add_all_msgs(MessageIterator &it);
    
    template <typename T>
    struct Adaptor : public MessageIterator {
        typename T::iterator wrapped;
        Adaptor(typename T::iterator w) : wrapped(w) { }
        virtual Message &get() {
            return *wrapped;
        }
        virtual void next() {
            ++wrapped;
        }
    };
    
    int main() {
        std::deque<Message> v;
        Adaptor<std::deque<Message> > a(v.begin());
        add_all_msgs(a);
    }
    

    I've checked that this compiles, but I haven't tested it and I've never used this design before. I also haven't bothered with const-ness - in practice you probably want a const Message &get() const. And at the moment the adaptor has no way of knowing when to stop, but then neither does the code you started with, so I've ignored that too. Basically you'd need a hasNext function which compares wrapped against an end iterator supplied to the constructor.

    You might be able to do something with a template function and const references, so that the client doesn't have to know about or declare that nasty Adaptor type.

    [Edit: come to think of it, it's probably better to have a stub add_all_msgs function template, that wraps its parameter in an Adaptor and then calls real_add_all_msgs. This completely hides the adaptor from the client.]

    0 讨论(0)
  • 2021-01-04 07:12
    template<class InputIterator>
    void add_all_msgs(InputIterator iter);
    

    Usage:

    std::deque<Message> deq;
    add_all_msgs(deq.begin());
    
    0 讨论(0)
  • 2021-01-04 07:12

    If you don't want to templatize your add_all_msgs function, you can use adobe::any_iterator:

    typedef adobe::any_iterator<Message, std::input_iterator_tag> any_message_iterator;
    void add_all_msgs(any_message_iterator begin, any_message_iterator end);
    
    0 讨论(0)
提交回复
热议问题