是否可以有一个可以同时使用向量和非向量类型作为参数的模板函数?

时间:2019-11-07 11:38:22

标签: c++ templates

请考虑以下声明:

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

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

是否有可能以某种方式将其合并为单个函数声明? 例如。像这样的东西:

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

4 个答案:

答案 0 :(得分:1)

模板参数可以是类型,非类型和模板。

我想你正在看这样的东西

#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是一个简单的类模板,可以通过std::initializer_list进行初始化。矩阵可以与std::vectorstd::list配合使用以保存其值。

live Demo

答案 1 :(得分:1)

您编码

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

已经接受std::vector。如果要在DoSomething方法中执行某些操作,如果T是向量,则该操作会有所不同,则you can use this approach会检查T是否是特定类型。不要忘记 模板 是代码生成器。

答案 2 :(得分:1)

好吧,template <class T> bool DoSomething(const T& value);也可以是带有任何向量的被调用者。是否可行取决于您要尝试执行的操作。模板只是代码生成器。因此,无论类T是什么,如果它具有所有必需的成员,则可以用作模板参数。

例如,以下方法将起作用:

#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)"
}

这是因为MyContainerstd::vector<std::string>都具有模板中使用的所有方法。实际上,这段代码几乎可以与所有STL容器一起使用。

答案 3 :(得分:1)

简短答案:通常您做不到。

诚实的答案:是的,可以做到,取决于您打算对参数进行什么处理。在抽象情况下,您将需要泛化函数原型,但是使用SFINAE仍然有两个模板特化,这使得三个声明而不是两个声明。

详细答案:在某些情况下,您可以利用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;
}