开发者

Templates, generic container and unique, C++

开发者 https://www.devze.com 2023-02-09 11:30 出处:网络
I have created a generic container extending capabilities of the vector... A new functionality for common functions fromhas been added.

I have created a generic container extending capabilities of the vector... A new functionality for common functions from has been added.

However, I have one problem: removing duplicate unique items. It consists of more steps: sorting, making items unique, erase... The new functionality lies in the renumbering of objects by primary ID and recomputing of some hashes. So it can not be done outside the class List...

Let us imagine the following example of generic container (simplified):

template <typename Item>
class List
{
protected:
            typename TList <Item>::Type items;
    ...
};

Comparatos have been implemented using functors...

template <typename Item>
class isEqual
{
        public:
            bool operator() ( const Item &i1, const Item &i2 )   const
            {
                  ...
            }
};

We create new list and remove duplicate items:

List <Object> list;
list.rem_duplic(items.begin(), items.end(), isEqual <Object>);

How do I implement function rem_duplicit having template parameter... If List represents a template class so the template parameter of the functor must be specified when declaring list:

List <Object, Comparator <Type> > list;

And it can be restrictive: duplicate items can be removed only by one criterion, functor can not be set when removing duplicate items... This construction is illegal:

template <typename Item>开发者_StackOverflow社区;
class List
{
protected:
            typename TList <Item>::Type items;
    public:
            template <typename Functor>
            void rem_duplic(typename TList <Item>::Type ::iterator begin, typename TList <Item>::Type ::iterator end, Functor <Item>) ();
            ...
};

template <typename Item> template <typename Functor>  //Illegal
void List<Item>::rem_duplic(typename TList <Item>::Type ::iterator begin,     typename TList   <Item>::Type ::iterator end, Functor <Item>)
{

}

How can I reasonably implement such a function, i.e. what can I do with the templatized parameter

Functor <Item> ? 

The internal functionality between {} is clear to me...


If you want to write a function that can take an arbitrary comparison function/functor as a parameter, make that function a template parameterized over the type of the comparator. For example:

template <typename ForwardIterator, typename Comparator>
void MakeUnique(ForwardIterator begin, ForwardIterator end,
                Comparator comp) {
    std::unique(begin, end, comp); // For example
}

Because the last argument is a template parameter, callers can pass in any type they want as long as it can be used as a comparator.


The <Item> in last argument declaration is superfluous. Just:

template <typename Functor>
void rem_duplic(items::iterator begin, items::iterator end, Functor f);

(note, that you can use the typedef you introduced above in the declaration to shorten it). The function does not care whether the passed argument is a template or not—all it needs to do is call it with the arguments (of type Item) and compiler will correctly substitute.

In fact, some times the functor will be a template and others it will be simply function comparing specified type.

Two notes:

  1. It's better to make your iterators template arguments too. Why limit yourself to items coming from your container. Remember, that plain pointers are iterators too and maybe you'll happen to have a static array one day or you'll get the data from other library or whatever.
  2. The semantics of the function is not really obvious. It's taking a range and it's doing something to it, but at the same time it's a member function so I suppose it's doing something to the invocant.

Note, that it is possible to declare template taking another template as it's argument, but you don't need anything like that here.

0

精彩评论

暂无评论...
验证码 换一张
取 消