【问题标题】:Passing std::vector for any type to a function将任何类型的 std::vector 传递给函数
【发布时间】:2009-10-28 23:19:42
【问题描述】:

给定:

template<typename T> class A {  
  B b;
  std::vector<T> vec1;
  std::vector<T> vec2;
}

我希望 B 有一个成员函数 fill(),它引用向量的引用,并根据 b 中包含的一些信息用 T 的值填充 vec2。
一种方法是为每个可能的参数 T 重载 fill():

fill(const std::vector<float>& a, std::vector<float>& b)

等等,但这将意味着很多不必要的重复,因为每个可能的 T 的操作都是相同的。在 fill() 内部,我可以使用 vector::value_type 进行计算,但我不知道如何声明它以这样一种方式,它需要每一种 std::vector。显而易见的方法是使用带有模板的免费功能。有没有更简单的方法?

【问题讨论】:

    标签: c++ templates vector


    【解决方案1】:

    模板化 B.

    template<typename T> class B {
      void fill(const std::vector<T>& a, std::vector<T>& b) { }
    };
    
    template<typename T> class A {  
      B<T> b;
      std::vector<T> vec1;
      std::vector<T> vec2;
    }
    

    如果不想模板化B,那就模板化填充函数:

    class B {
      template<typename T>
      void fill(const std::vector<T>& a, std::vector<T>& b) {}
    };
    

    【讨论】:

    • 更多信息:B 是具有纯虚函数的继承层次结构的一部分,并包装在指向基类的智能指针中。用户将需要使用与 A 相同的类型来实例化 B(这会增加出错的可能性),并且对于类的用户来说并不明显,所以我宁愿避免这样做。
    • 我意识到重构大型层次结构很痛苦,但您也可以尝试使用策略类作为模板参数而不是传入智能指针,并且显然(根据您的描述)牺牲类型安全灵活性。
    【解决方案2】:

    你已经得到了很多答案,但我必须不同意他们,至少在某种程度上。我的直接反应是您根本不应该将 vector 传递给b::fill。相反,您应该传递一个迭代器(或者可能是一对迭代器)。其余的大部分是正确的:这仍然意味着fill 应该是模板成员函数。当你调用它时,你可能想要传递一个std::back_insert_iterator,通常使用std::back_inserter 获得。

    您所说的部分内容似乎自相矛盾:如果b::fill 修改了vec1vec2,它们可能应该作为对const 的引用传递。诚然,const 在应用于容器时并没有其通常的含义,但事实仍然是,将对 const 的引用传递给其唯一意图显然是修改所传递内容的函数似乎是错误的。

    【讨论】:

    • 同意我同意你应该传递迭代器范围而不是容器的观点。他还应该检查迭代器类型擦除。 Thomas Becker 和 Adob​​e 公共图书馆一样有一个 any_iterator 类。
    • 关于 const 的引用:只会修改第二个向量。关于使用迭代器:填充操作将相当繁重(大量插入),它可以从 vector::reserve(int) 中受益。如何使用 std::back_inserter 获得这种性能改进?
    • reserve 保留空间(也是构造函数之一)。它不创建对象。您可以使用 reserve() 而不是 back_insert 。它构造(或分配给)预分配空间的结果,这正是您想要的。 (并且,对于结构繁重且分配轻的对象,您可以创建具有所需大小的向量而不使用 back_inserter)
    • 很遗憾,不——insert_iterators 没有理由不能将reserve 传递给底层容器,但它没有在当前接口中定义。
    【解决方案3】:

    模板化fill

    class B {
    public:
      template<typename T>
      void fill(const std::vector<T>& a, std::vector<T>& b)
      { /*...*/ }
      //...
    };
    

    (根据您的描述,b 应该是 const std::vector&lt;T&gt;&amp;。)

    【讨论】:

      【解决方案4】:

      您可以将 B 定义为模板类,填充为模板函数(在非模板类 B 中),或者,我最喜欢的是,使用标准的 std::transform/std::copy/std::fill,它们已经是模板函数,填充您的向量。
      (全部位于&lt;algorithm&gt; 标头内)。

      【讨论】:

      • 不知道非模板类中的模板成员函数。迄今为止最好的选择 std::transform。
      猜你喜欢
      • 2020-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 2017-04-10
      • 2019-05-10
      相关资源
      最近更新 更多