Home > database >  Make a common function for a "type" and the vector of "type" using templates in
Make a common function for a "type" and the vector of "type" using templates in

Time:06-24

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?

CodePudding user response:

With just little changes you can do so

#include <iostream>
#include <vector>

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

template <typename T>
void doSomeThing(T element)
{
  // do Something else if it was not a vector
}

CodePudding user response:

For example you can write

template <class T>
void doSomeThing( const std::vector<T> &vec )
{
    for ( const auto &element : vec )
    {
        std::cout << element << ' ';
    }
    std::cout << '\n';
}

template <class T>
void doSomeThing( const T &obj )
{
    for ( const auto &element : obj )
    {
        std::cout << element << ' ';
    }
    std::cout << '\n';
}

Here is a demonstration program.

#include <iostream>
#include <vector>
#include <type_traits>

template <class T>
void doSomeThing( const std::vector<T> &vec )
{
    std::cout << std::boolalpha
        << std::is_same_v<std::decay_t<decltype( vec )>, std::vector<T>>
        << '\n';

    for ( const auto &element : vec )
    {
        std::cout << element << ' ';
    }
    std::cout << '\n';
}

template <class T>
void doSomeThing( const T &obj )
{
    std::cout << std::boolalpha
        << std::is_same_v<std::decay_t<decltype( obj )>, std::vector<T>>
        << '\n';
    for ( const auto &element : obj )
    {
        std::cout << element << ' ';
    }
    std::cout << '\n';
}

int main() 
{
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    doSomeThing( v );

    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    
    doSomeThing( a );
}

The program output is

true
0 1 2 3 4 5 6 7 8 9 
false
0 1 2 3 4 5 6 7 8 9 

CodePudding user response:

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));
}
  • Related