Search code examples
c++templatesvectorduplicatesstdvector

Make a common function for a "type" and the vector of "type" using templates in C++


I was writing functions and came across this situation:

void doSomeThing(std::vector<someType> vec)
{
  for(element : vec)
  {
    // do Something different if it is in vector
  }
}

void doSomeThing(someType element)
{
  // do Something else if it was not a vector
}

I need them to be separate like above stated. I was wondering if there was a way using templates to deduce the type and do the processing accordingly?


Solution

  • Well, yes, it is possible.

    For example, you could do;

    template<class someType>
    void doSomeThing( const someType &obj )
    {
          // do something assuming someType is not a vector of something
    }
    
    template<class someType>
    void doSomeThing( const std::vector<someType> &obj )
    {
          // do something different if a vector<someType> is passed
    }
    
    int main()
    {
        int x = 24;
        std::vector<int> a{1,2,3};     // assuming C++11 and later
    
        doSomeThing(x);     //  will call a specialisation of the first form above
        doSomething(a);     //  will call a specialisation of the second form above
    }
    

    Personally, I'd do it slightly differently though - instead of overloading for a vector, I'd overload for a pair of iterators. For example, assuming doSomething() is just function that prints to std::cout

    template<class someType>
    void doSomeThing( const someType &obj )
    {
          std::cout << obj;
    }
    
    template<class Iter>
    void doSomeThing( Iter begin, Iter end)
    {
        while(begin != end)
        {
           std::cout << *begin << ' ';
           ++begin;
        }
        std::cout << '\n';
    }
    

    which will work with iterators from any standard container (e.g. specialisations of std::vector, std::list) or anything else that can provide a pair of valid iterators.

    int main()
    {
        int x = 24;
        std::vector<int> a{1,2,3};     // assuming C++11 and later
        std::list<double> b {42.0, 45.0};
    
    
        doSomeThing(x);     
        doSomething(std::begin(a), std::end(a));
        doSomething(std::begin(b), std::end(b));
    }