【问题标题】:C++ writing a generic functions for all std::setsC++ 为所有 std::sets 编写通用函数
【发布时间】:2026-02-13 17:55:01
【问题描述】:

我需要编写一个小函数来创建一个新的 std::set 从现有元素中获取最后 n 个元素。

代码如下:

template <typename S, typename T, typename Z>
std::set<T,S,Z> get_first_subset(std::set<T,S,Z> const& set, size_t size) {
    if (size == 0)
        return std::set<T,S,Z>();

    typename std::set<T,S,Z>::reverse_iterator j = set.rbegin();
    std::advance(j, size - 1);

    return std::set<T,S,Z> ((++j).base(), set.end());
}

它可以工作,但是由于我不需要访问类型 T、S 和 Z,我想知道是否有一种方法可以简单地说“任何 std::set”而无需三个模板参数。

【问题讨论】:

    标签: c++ templates stdset


    【解决方案1】:

    让它更通用怎么样:

    #include <iterator>
    template <typename T>
    T get_first_subset(T const& set, size_t size) {
      if (size == 0)
        return T();
    
      typename T::reverse_iterator j = set.rbegin();
      std::advance(j, size - 1);
    
      return T ((++j).base(), set.end());
    }
    

    然后:

    int main() {
      std::set<int> s{10, 2,4,6,7,8,9}, s1;
      s1 = get_first_subset(s, 4);
      for (auto i:s1) std::cout << i << " ";
      std::cout << std::endl;
    }
    

    输出:

    7 8 9 10
    

    您还可以使用可变参数模板 (C++11)、大括号初始化和auto 关键字来避免重复自己:

    template <typename ...S>
    std::set<S...> get_first_subset(std::set<S...> const& set, size_t size) {
      if (size == 0) return {};
      auto j = set.rbegin();
      std::advance(j, size - 1);
      return  {(++j).base(), set.end()};
    }
    

    【讨论】:

    • 嗯,是的。我想它有效。当我想要一个特定的标准数据结构时,我仍然很好奇是否可以避免所有这些模板参数。
    • @Paolo.Bolzoni - 您担心用法或函数定义和签名?因为如果它是用法并且您可以使用C++11,您可以使用auto 并获得类似(测试):auto subset = get_first_subset( some_set, some_size );
    • @Paolo.Bolzoni 您可以在 C++11 中使用可变参数模板来避免指定多个模板参数