【问题标题】:Is it possible to have a template function that can take both vector and non-vector type as a parameter?是否可以有一个模板函数可以同时接受向量和非向量类型作为参数?
【发布时间】:2019-11-07 11:38:22
【问题描述】:

考虑以下声明:

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(...);

【问题讨论】:

  • 你是什么意思“将其合并为单个函数声明”?你想解决什么问题。不,不是关于“将其合并为单个函数声明”,而是您认为解决方案是“将其合并为单个函数声明”的任何问题。
  • 我想知道是否可以为这样的函数声明一个,例如模板 bool DoSomething(...);为什么?好奇心还不够吗?同样,当我们在这里的时候,什么时候好奇心会受到投票的惩罚?
  • 你还没有解释这个“这样的功能”应该做什么,或者它应该如何工作。唯一能告诉你的是template&lt;class T, class D&gt; bool DoSomething(); 是一个有效的C++ 函数声明。除非这实际上是您要问的,否则不清楚您要问的是什么,除非您说清楚,否则没有人可以帮助您。再来一次:你想解决什么真正的问题。不,不是关于声明这样一个函数的问题,而是你认为解决方案是声明这样一个函数的任何问题。
  • template &lt;class T&gt; bool DoSomething(const T&amp; value); 也将接受任何类型的 std::vector。问题是你打算用它做什么。
  • @DmitriiMotorygin 我猜你收到了反对票,因为这似乎是一个信息很少的 XY 问题。

标签: c++ templates


【解决方案1】:

你编码

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

已经接受std::vector。如果你想在你的 DoSomething 方法中做一些不同的事情,如果 T 是一个向量,那么 you can use this approach 来检查 T 是否是一个特定的类型。不要忘记模板是代码生成器。

【讨论】:

    【解决方案2】:

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

    我猜你正在看类似这样的东西

    #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

    【讨论】:

      【解决方案3】:

      嗯,template &lt;class T&gt; bool DoSomething(const T&amp; 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&lt;std::string&gt; 都具有模板中使用的所有方法。实际上,这段代码应该适用于几乎所有的 STL 容器。

      【讨论】:

        【解决方案4】:

        简答:通常你不能。

        诚实回答:是的,可以做到,这取决于你打算如何处理争论。在抽象情况下,您需要泛化函数原型,但仍然有两个使用 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;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-03
          • 2023-03-28
          • 2011-08-08
          • 1970-01-01
          相关资源
          最近更新 更多