【问题标题】:single template function to display contents of different container [duplicate]显示不同容器内容的单个模板功能[重复]
【发布时间】:2017-11-20 03:59:32
【问题描述】:

我有一个使用以下方法构造的矢量容器:

vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);

并使用以下方法构造双端队列容器:

deque<int> deq;
deq.push_front(1);
deq.push_front(2);
deq.push_front(3);

我想要一个模板函数来显示这两个容器和所有数据类型的内容。为了处理不同的数据类型,我制作了一个这样的模板函数:

template <typename T>
void display(vector<T> vec)
{
    for(int i = 0; i < vec.size(); ++i)
    {
        cout << vec[i] << endl;
    }
    cout << endl;
}

目前它适用于矢量,我怎样才能使它适用于所有容器,如双端队列和列表?

【问题讨论】:

    标签: c++ list templates vector deque


    【解决方案1】:

    许多 STL 容器都支持以对作为值类型的范围

    #include <iostream>
    #include <deque>
    #include <vector>
    #include <map>
    
    using std::cout;
    using std::endl;
    
    namespace detail {
        template <typename First, typename Second>
        void print_element(const std::pair<First, Second>& pr) {
            cout << pr.first << " " << pr.second << endl;
        }
    
        template <typename Type>
        void print_element(const Type& element) {
            cout << element << endl;
        }
    } // namespace detail
    
    template <typename Container>
    void print_all(const Container& container) {
        for (const auto& element : container) {
            detail::print_element(element);
        }
    }
    
    
    int main() {
    
        auto v = std::vector<int>{1, 2, 3};
        auto d = std::deque<int>{1, 2, 3};
        auto m = std::map<int, int>{{1, 2}};
        print_all(v);
        print_all(d);
        print_all(m);
    
        return 0;
    }
    

    【讨论】:

    • 很好奇,我很好奇(抱歉忍不住),你为什么只为 std::pair 做一个特例?
    • @jschultz410 因为许多像std::unordered_mapstd::map 这样的容器在使用它们的迭代器进行迭代时都有std::pair 作为值类型。是否还有其他 STL 容器使用的值包装器我错过了考虑?
    • 我想如果你想更通用,你会专注于 std::tuple。我的观点是,可能有各种各样的类型没有输出运算符。我只是想知道您为什么选择 std::pair 进行特殊处理。我想因为它是标准库中常见的类型是一个很好的理由。
    【解决方案2】:

    大概是这样的:

    template <typename C>
    void display(const C& container) {
      std::copy(std::begin(container), std::end(container),
        std::ostream_iterator<decltype(*std::begin(container))>(std::cout, "\n"));
    }
    

    【讨论】:

    • 为什么是decltype(*std::begin(container)) 而不是typename C::value_type
    • @Caleth 为什么不呢?这样可以减少对C 的要求。
    • 这不会为容器的每个元素调用一个复制构造函数吗?
    • @jschultz410 它不会看到 en.cppreference.com/w/cpp/iterator/ostream_iterator/operator%3Dostream_iterator 的赋值接受 const 引用的值
    • @jschultz410 我觉得ostream_iterator 是在std::copy 之上的一个黑客,而不是std::copy 在个人所做的事情上并不普遍
    【解决方案3】:

    我猜你可能会使用基于范围的 for 循环:

    template<typename C>
    void display(const C& container)
    {
        for (const auto& e : container)
        {
            std::cout << e << std::endl;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-17
      • 2018-10-11
      • 2020-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-13
      • 2017-11-29
      相关资源
      最近更新 更多