Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you create a static template member function that performs actions on a template class?

Tags:

People also ask

How do you create a template function in C++?

Defining a Function TemplateA function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

What happens when there is static member in a template class function?

The static member is declared or defined inside the template< … > class { … } block. If it is declared but not defined, then there must be another declaration which provides the definition of the member.

What is template explain function templates and class templates with example?

Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. To simply put, you can create a single function or single class to work with different data types using templates. C++ template is also known as generic functions or classes which is a very powerful feature in C++.

How do you define a template member function?

You may define a template member function outside of its class template definition. When you call a member function of a class template specialization, the compiler will use the template arguments that you used to generate the class template.


I'm trying to create a generic function that removes duplicates from an std::vector. Since I don't want to create a function for each vector type, I want to make this a template function that can accept vectors of any type. Here is what I have:

//foo.h  Class Foo {  template<typename T> static void RemoveVectorDuplicates(std::vector<T>& vectorToUpdate);  };  //foo.cpp  template<typename T> void Foo::RemoveVectorDuplicates(std::vector<T>& vectorToUpdate) { for(typename T::iterator sourceIter = vectorToUpdate.begin(); (sourceIter != vectorToUpdate.end() - 1); sourceIter++) {         for(typename T::iterator compareIter = (vectorToUpdate.begin() + 1); compareIter != vectorToUpdate.end(); compareIter++) {             if(sourceIter == compareIter) {                 vectorToUpdate.erase(compareIter);             }         }     } }  //SomeOtherClass.cpp  #include "foo.h"  ...  void SomeOtherClass::SomeFunction(void) {     std::vector<int> myVector;      //fill vector with values      Foo::RemoveVectorDuplicates(myVector); } 

I keep getting a linker error, but it compiles fine. Any ideas as to what I'm doing wrong?

UPDATE: Based on the answer given by Iraimbilanja, I went and rewrote the code. However, just in case someone wanted working code to do the RemoveDuplicates function, here it is:

//foo.h  Class Foo {      template<typename T>     static void RemoveVectorDuplicates(T& vectorToUpdate){         for(typename T::iterator sourceIter = vectorToUpdate.begin(); sourceIter != vectorToUpdate.end(); sourceIter++) {             for(typename T::iterator compareIter = (sourceIter + 1); compareIter != vectorToUpdate.end(); compareIter++) {             if(*sourceIter == *compareIter) {                 compareIter = vectorToUpdate.erase(compareIter);             }         }     } }; 

Turns out that if I specify std::vector in the signature, the iterators don't work correctly. So I had to go with a more generic approach. Also, when erasing compareIter, the next iteration of the loop produces a pointer exception. The post decrement of compareIter on an erase takes care of that problem. I also fixed the bugs in the iterator compare and in the initialization of compareIter in the 2nd loop.

UPDATE 2:

I saw that this question got another up vote, so figured I'd update it with a better algorithm that uses some C++14 goodness. My previous one only worked if the type stored in the vector implemented operator== and it required a bunch of copies and unnecessary comparisons. And, in hindsight, there is no need to make it a member of a class. This new algorithm allows for a custom compare predicate, shrinks the compare space as duplicates are found and makes a significantly smaller number of copies. The name has been changed to erase_duplicates to better conform to STL algorithm naming conventions.

template<typename T> static void erase_duplicates(T& containerToUpdate)  {     erase_duplicates(containerToUpdate, nullptr); }  template<typename T> static void erase_duplicates(T& containerToUpdate,    std::function<bool (typename T::value_type const&, typename T::value_type const&)> pred)  {     auto lastNonDuplicateIter = begin(containerToUpdate);     auto firstDuplicateIter = end(containerToUpdate);     while (lastNonDuplicateIter != firstDuplicateIter) {         firstDuplicateIter = std::remove_if(lastNonDuplicateIter + 1, firstDuplicateIter,              [&lastNonDuplicateIter, &pred](auto const& compareItem){             if (pred != nullptr) {                 return pred(*lastNonDuplicateIter, compareItem);             }             else {                 return *lastNonDuplicateIter == compareItem;             }         });         ++lastNonDuplicateIter;     }     containerToUpdate.erase(firstDuplicateIter, end(containerToUpdate)); }