简体   繁体   中英

Is it possible to have a template function that can take both vector and non-vector type as a parameter?

Consider the following declaration:

template <class T>
bool DoSomething(const T& value);

template <class D>
bool DoSomething(const std::vector<D>& value);

Is it possible to somehow unite this into single function declaration? Eg something like that:

template <class T, class D> bool DoSomething(...);

Template parameters can be types, non-types, and templates.

And I suppose you are looking at something like this

#include <iostream>
#include <list>
#include <vector>
#include <string>

template <typename T, template <typename, typename> class Cont > 
class Matrix{
public:
  explicit Matrix(std::initializer_list<T> inList): data(inList){
for (auto d: data) std::cout << d << " ";
  }
  int getSize() const{
    return data.size();
  }

private:
  Cont<T, std::allocator<T>> data;  
};

int main(){

  std::cout << std::endl;
  Matrix<int, std::vector> myIntVec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
  std::cout << std::endl;
  std::cout << "myIntVec.getSize(): " << myIntVec.getSize() << std::endl;
  Matrix<std::string, std::list> myStringList{"one", "two", "three", "four"};  
  std::cout << std::endl;
  std::cout << "myStringList.getSize(): " << myStringList.getSize() << std::endl;

  std::cout << std::endl;

}

Matrix is a simple class template, that can be initialised by a std::initializer_list . A Matrix can be used with a std::vector , or a std::list to hold its values.

live Demo

You code

template <class T>
bool DoSomething(const T& value);

is already accepting std::vector . If you want to do something in your DoSomething method which is different if T is a vector, then you can use this approach to check if the T is a specific type. Don't forget that templates are code generators.

Well, template <class T> bool DoSomething(const T& value); can also be calles with any vector. If it works depends on what you are trying to do. Templates are just code generators. So whatever class T is, it can be used as template paramter if it has all the required members.

For example the following would work:

#include <iostream>
#include <vector>
#include <string>

class MyContainer {
public:
    size_t size() const
    {
        return 2;
    }

    int front() const
    {
        return 0;
    }

    int back() const
    {
        return 1;
    }
};

template<class T>
void foo(const T& t)
{
    if (t.size() >= 2)
    {
        std::cout << "(" << t.front() << ", " << t.back() << ")" << std::endl;
    }
}

int main()
{
    std::vector<std::string> stringVec{ "abc", "def" };

    MyContainer cont;

    foo(stringVec); // prints "(abc, def)"
    foo(cont); // prints "(0, 1)"
}

That's because both MyContainer and std::vector<std::string> have all the methods that are uses in the template. Actually this code should work with almost all STL-Containers.

Short answer : Geneally you can't.

Honest answer : Yes, it can be done, depends on what you plan to do with argument. In abstract case you would need to generalize the function prototype, but still have two specializations of template using SFINAE, which makes three declarations instead of two.

Long answer : In some cases you can take advantage of if constexpr

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

template<typename Test, template<typename...> class Ref>
struct is_specialization : std::false_type {};

template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref>: std::true_type {};

template <class T> bool DoSomething(const T& arg) 
{ 
    if constexpr(is_specialization<T, std::vector>::value) 
    {
        return !arg.empty();    
    } else
    {
        return bool(arg);
    }
}

int main()
{
    std::vector<int> s;
    std::cout << DoSomething(s) << std::endl;
    std::cout << DoSomething(1) << std::endl;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM