【问题标题】:C++ same function on vectors of different typesC++ 对不同类型向量的相同函数
【发布时间】:2014-11-21 09:21:42
【问题描述】:

我有一个非常简单的函数,可以将vector<double> 打印到 cout。我有相同的功能,它采用 vector<int> 代替。如果可能的话,我可以用一个函数替换这些向量吗?

void printv(vector<double> vec)
{
    copy(vec.begin(),vec.end(), ostream_iterator<double>(cout," "));
    cout << endl;
}

void printv(vector<int> vec)
{
    copy(vec.begin(),vec.end(), ostream_iterator<int>(cout," "));
    cout << endl;
}

如果有人建议专门用于打印任何类型的矢量的解决方案,我对将矢量保存到文件的功能也有同样的问题,所以重点是一般问题,而不是专门与打印有关。

提前致谢!

【问题讨论】:

    标签: c++ function vector types


    【解决方案1】:

    是的,使用模板:

    template<typename T>
    void printv(std::vector<T> const &vec)
    {
        std::copy(vec.cbegin(),vec.cend(), ostream_iterator<T>(std::cout," "));
        std::cout << std::endl;
    }
    

    或者,您可以为std::vector 定义一个重载operator&lt;&lt; 的模板,如下所示:

    template<typename T>
    std::ostream& operator<<(std::ostream &out, std::vector<T> const &v) {
      std::copy(v.cbegin(), v.cend(), std::ostream_iterator<T>(out, " "));
      out << std::endl;
      return out;
    }
    
    int main() {
      std::vector<int> iv {1, 2, 3, 4, 5};
      std::vector<double> dv {1.1, 1.2, 1.3, 1.4, 1.5};
      std::cout << iv << std::endl;
      std::cout << dv << std::endl;
    }
    

    LIVE DEMO

    【讨论】:

      【解决方案2】:

      当然。这就是 C++ 的意义所在。

      template<typename T>
      void printv(vector<T> const& vec)
      {
          copy(vec.begin(), vec.end(), ostream_iterator<T>(cout," "));
          cout << endl;
      }
      

      只要T 是“可输出流式”就可以工作。

      注意:我已将const&amp; 添加到签名中以避免复制。


      现在,你可以更进一步:

      template<typename Container>
      void print(Container const& c)
      {
          using std::begin;
          using std::end;
          using std::copy;
      
          copy(begin(c), end(c), std::ostream_iterator<typename Container::value_type>(cout, " "));
          cout << endl;
      }
      

      使其适用于所有标准容器,而不仅仅是矢量。

      【讨论】:

      • copy 可能会被忽略
      • @0d0a 为什么要靠实力?在很多情况下它不会。 (其实我想不出它不会复制的任何情况)
      • 不要依赖可能,只知道可能会被忽略,这只是信息
      • @0d0a 你能举个例子吗?
      • 添加using std::begin; using std::end; within 函数主体添加了功能:C 样式数组支持和更容易扩展自定义范围支持对象。 (直接std::begin 电话更糟糕)在我看来,这是一个最佳实践。
      【解决方案3】:

      试试下面的

      #include <iostream>
      #include <vector>
      #include <cstring>
      
      template <class T>
      
      std::ostream & print( T &c, std::ostream &os = std::cout )
      {
          for ( auto x : c ) os << x << ' ';
          os << std::endl;
      
          return os;
      }
      
      template <class T, size_t N>
      
      std::ostream & print( T ( &a )[N], std::ostream &os = std::cout )
      {
          for ( auto x : a ) os << x << ' ';
          os << std::endl;
      
          return os;
      }
      
      template <class T>
      
      std::ostream & print( T *a, size_t n, std::ostream &os = std::cout )
      {
          for ( auto p = a; p != a + n; ++p ) os << *p << ' ';
          os << std::endl;
      
          return os;
      }
      
      int main() 
      {
          int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
          double b[] = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
          char s[] = "Hello zooombini";
      
          std::vector<int> v1( a, a + sizeof( a ) / sizeof( *a ) );
          std::vector<double> v2( b, b + sizeof( b ) / sizeof( *b ) );
      
          print( a );
          print( b );
          print( v1 );
          print( v2 );
          print( s, std::strlen( s ) );
      
          return 0;
      }
      

      输出是

      0 1 2 3 4 5 6 7 8 9 
      0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 
      0 1 2 3 4 5 6 7 8 9 
      0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 
      H e l l o   z o o o m b i n i
      

      或者你甚至可以再添加一个重载函数

      #include <iostream>
      #include <vector>
      #include <cstring>
      
      template <class T>
      
      std::ostream & print( T &c, std::ostream &os = std::cout )
      {
          for ( auto x : c ) os << x << ' ';
          os << std::endl;
      
          return os;
      }
      
      template <class T, size_t N>
      
      std::ostream & print( T ( &a )[N], std::ostream &os = std::cout )
      {
          for ( auto x : a ) os << x << ' ';
          os << std::endl;
      
          return os;
      }
      
      template <class T>
      
      std::ostream & print( T *a, size_t n, std::ostream &os = std::cout )
      {
          for ( auto p = a; p != a + n; ++p ) os << *p << ' ';
          os << std::endl;
      
          return os;
      }
      
      std::ostream & print( const char *s, std::ostream &os = std::cout )
      {
          return os << s << std::endl;
      }
      
      std::ostream & print( char *s, std::ostream &os = std::cout )
      {
          return os << s << std::endl;
      }
      
      int main() 
      {
          int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
          double b[] = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
          int *p = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
          char s[] = "Hello zooombini";
      
          std::vector<int> v1( a, a + sizeof( a ) / sizeof( *a ) );
          std::vector<double> v2( b, b + sizeof( b ) / sizeof( *b ) );
      
          print( a );
          print( b );
          print( p, 10 ) << std::endl;
      
          print( v1 );
          print( v2 );
          print( s, std::strlen( s ) );
          print( s );
      
          delete []p;
      
          return 0;
      }
      

      输出是

      0 1 2 3 4 5 6 7 8 9 
      0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 
      0 1 2 3 4 5 6 7 8 9 
      
      0 1 2 3 4 5 6 7 8 9 
      0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 
      H e l l o   z o o o m b i n i 
      Hello zooombini
      

      【讨论】:

      • 你可以用begin/end代替a+sizeof(a)/sizeof(*a),这看起来很糟糕。
      • @Bartek Banachewicz 对于这样一个简单的代码,不需要包含标题
      • 所以您宁愿采用晦涩难懂的解决方案而不是包含标准库头文件? 来吧。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 2020-03-05
      相关资源
      最近更新 更多