   Writing generic STL functions
  I want to write my own version of the std::copy function, which works the same as the original, but the container is treated a a circular buffer.if(iterFirst > iterLast){ // Need to wrapout.insert(out.end(),iterFirst,in.end());out.insert(out.end(),in.begin(),iterLast);}elseout.insert(out.end(),iterFirst,iterLast);So if I want to insert elements from positions 7 through to 4, it will copy elements 7,8,9,0,1,2,3, for example.I want to make this into a template function that works for any STL container type, but I'm not sure how to use the iterator types. How do you write a generic wrappedCopy function?   
  First write the function in a non-templated fashion. Have the inputs be a specific type of iterator, pointer-to-int for example. Nail down the interface for your function at this stage.Do not write the interface in terms of a container -- iterators only. You'll assume that the output pointer(s) point in to a buffer of the appropriate size. When the function is made generic, the user can pass something like a std::back_insert_iterator if they want the container to grow as eleemnts are written. It's quite common to this with std::copy, for example.Once it's working, sprinkle in some templates by adding type parameters and use those throughout instead of a pointer. Try to use as few "features" of the pointer as possible without sacrificing efficiency of the algorithm. For example, if you can avoid random-access jumps, do so.  In its current form, it looks like your function might need compare iterators (iterFirst > iterLast). Is this always necessary? When "genericizing" the function, it would mean it could only accept random access iterators. Would you intuitively expect the function to work with std::list iterators? If so, think about how to make that happen.It might be the case that the implementation chooses a different path based on the category of iterator passed in. Perhaps you can do it a little bit faster if the iterators are random access iterators?Inside the function, use static asserts to ensure that the client is passing iterators of sufficient category (forward, bidirectional or random access for input probably and an output iterator for output).Inside the function, you may want to swap() elements. Rather than calling std::swap directly, write "using std::swap;" at the top and then call swap() without qualification. This will let ADL pick up swap functions that people have defined for custom types.   ;  To do it without passing the container parameter, I'd need to pass parameters for begin(), end(), rangeBegin() and rangeEnd(). I often work with indices instead of iterators, which is a lot simpler when a container is being resized during an operation, which is often the case. In which case I could require passing a reference to the container itself.Am I correct in saying that the various iterator types are not actual datatypes/classes, but rather an indication of which STL containers the various functions are compatible with? The iterator parameters of the MSVC <algorithm> methods are just template types, so if you pass an incorrect iterator type, there's no type mismatch error, and the compiler instead raises an error somewhere deep within the bowels of the STL's implementation.What if I did something like this:template<class Container,typename OutIter>void wrappedInsert(OutIter dest,const Container& source,Container::const_iterator rangeStart,Container::const_iterator rangeEnd){}   ;Quote:Original post by taz0010To do it without passing the container parameter, I'd need to pass parameters for begin(), end(), rangeBegin() and rangeEnd(). I often work with indices instead of iterators, which is a lot simpler when a container is being resized during an operation, which is often the case. In which case I could require passing a reference to the container itself.You could. But if you want your algorithm to be like the existing STL algorithms, this isn't the way to do it. The STL provides std::back_insert_iterator and std::insert_iterator to expand a container as necessary. But perhaps you don't mind if your algorithm isn't in the same form as those provided by the STL. Your call...Quote:Am I correct in saying that the various iterator types are not actual datatypes/classes, but rather an indication of which STL containers the various functions are compatible with?Iterator categories, yes. More specifically, by saying an iterator belongs to a particular category, we are advertising the subset of the pointer-like interface that the iterator type has.So if you hand me an output iterator over a range of ints, I know I can write "*it++ = 4;". However, there's no guarantee that i can write "--*it = 4;". That would require a bidirectional iterator.The iterator categories defined by the C++ standard library are input iterators, output iterators, forward iterators, bidirectional iterators and random access iterators. See your C++ reference for more (but I'm also happy to answer further questions on them).Quote:The iterator parameters of the MSVC <algorithm> methods are just template types, so if you pass an incorrect iterator type, there's no type mismatch error, and the compiler instead raises an error somewhere deep within the bowels of the STL's implementation.Yep, that's a problem with templatey code, in general. To help with this, I would add a whole bunch of static assertions at the top of the algorithm's code. For example:// InputIter type must be an input iteratortypedef typename std::iterator_traits<InputIter>::iterator_category cat;BOOST_STATIC_ASSERT((is_convertible<cat, std::input_iterator_tag>::value));Quote:What if I did something like this:template<class Container,typename OutIter>void wrappedInsert(OutIter dest,const Container& source,Container::const_iterator rangeStart,Container::const_iterator rangeEnd){}You can (though you'll need some "typename"s sprinkled in there). There's nothing "wrong" with doing it that way, but it's probably less generic than it could be.If I'm understanding you correctly, your algorithm sounds like it will be functionally equivalent to doing an std::copy followed by an std::rotate. Those know nothing about containers and yet when the appropriate kinds of iterator are used, they can work with vectors, lists, strings and even arrays (and arrays have no const_iterator typedef).So what you're proposing doesn't need to know anything about a container, really. And that's the whole point of the "STL way" to decouple the algorithm from the type of range or container.   ;  If you want to copy entire containers - just starting at some middle point and wrapping around - try std::rotate.   