如何仅使用容器进行模板

How can I template with container only?

本文关键字:何仅使      更新时间:2023-10-16

我认为我的标题不准确,所以只需转到代码。

namespace Fobaizer
{
  template <typename T, typename C>
  static T GetItemFromContainer(const C &container) {
    T item = container[0]; // do something. 0 or iterator
    return item;
  }
}

例:

MyClass myClass = Fobaizer::GetItemFromContainer<MyClass, vector<MyClass>(myVector);

MyClass myClass = Fobaizer::GetItemFromContainer<MyClass, deque<MyClass>(myDeque);

这里 C 是任何容器,如 std::dequestd::vector 。我搜索没有任何库(升压、QT 等)的 C98 解决方案。

事实上,我正在寻找类似 C# IEnumerable的东西。

知道吗?

谢谢。

template <typename C>
static typename C::value_type GetItemFromContainer(const C & container) {
    typename C::value_type item = container[0]; // do something. 0 or iterator
    return item;
 }

基本上每个容器都定义了成员类型定义:

 value_type
 reference
 const_reference
 iterator
 const_iterator

因此,如果要按值返回,C::reference如果要按引用返回,则可以只使用 C::value_type,等等。

我要做的是创建一个测试来检查是否可以在容器上调用std::beginstd::end。 然后对这些容器和std::advance使用迭代器,将迭代器推进到需要它们的位置。

这种方法的优点是你可以接受不会重载operator[]的容器(例如std::list

    #include <utility>
    #include <type_traits>
    #include <vector>
    #include <list>
    namespace sfinae_true_details
    {
        template <class>
        struct sfinae_true : std::true_type{};
    }
    template <class T>
    auto test_has_begin_end(int) ->
        sfinae_true_details::sfinae_true<decltype(std::begin(std::declval<T>()) ==
                                                  std::end(std::declval<T>())>;        
    template <class>
    std::false_type test_has_begin_end(long);
    template <class T>
    struct has_begin_end : decltype(test_has_begin_end<T>(0)){};
    int main()
    {
        static_assert(has_begin_end<std::vector<int> >::value, "");
        static_assert(has_begin_end<std::list<float> >::value, "");
        static_assert(has_begin_end<int>::value, "Expected to fail here");
        return 0;
    }

那么你的用法将是:

      template <typename T, typename C>
      static T GetItemFromContainer(const C &container) {
          static_assert(has_begin_end<C>::value, "Must pass a container for which "
                        "std::begin and std::end are callable");
          T item = *std::begin(container); // do something. 0 or iterator
          auto iter = std::begin(container);
          std::advance(iter, 5);
          item = *iter; // equivalent to container[5] for RandomAccessContainers
          return item;
      }

为什么要在C++中执行 IEnumerable,迭代器是迭代集合的不错选择。

相关文章: