通用打印函数,可以处理列表和标量实体

Generic print function which behaves handles both lists as well as scalar entities?

本文关键字:列表 处理 标量 实体 打印 函数      更新时间:2023-10-16

我想写一个函数,我可以调用每当我需要打印的东西。然而,当打印矢量或列表时,我需要它的行为略有不同。此外,一个vector或list也可以包含另一个vector或list。

我的第一个方法是这样做的:

#include <iostream>
#include <list>
#include <vector>
using namespace std;
template <typename T>
void
print(const vector<T>& v) {
    cout << "[";
    bool isFirst = true;
    for (const T& e : v) {
        if (isFirst) isFirst = false;
        else cout << ",";
        print(e);
    }
    cout << "]";
}
template <typename T>
void
print(const list<T>& l) {
    cout << "[";
    bool isFirst = true;
    for (const T& e : l) {
        if (isFirst) isFirst = false;
        else cout << ",";
        print(e);
    }
    cout << "]";
}
template <typename T>
void
print(const T& v) {
    cout << v;
}
int
main(int argc, char** argv) {
    vector<int> v;
    print(v);
    return 0;
}

如你所见,打印向量和列表有很多重复的代码,但我不知道如何组合它们。在任何情况下,代码都无法编译,因为编译器试图将标量实体(例如int)的打印与print的第一个实现匹配,而不是最后一个实现:

g++ -std=c++11 test.cpp
test.cpp: In instantiation of ‘void print(const std::vector<T>&) [with T = int]’:
test.cpp:42:12:   required from here
test.cpp:15:16: error: no matching function for call to ‘print(const int&)’
         print(e);
                ^
test.cpp:15:16: note: candidate is:
test.cpp:9:1: note: template<class T> void print(const std::vector<T>&)
 print(const vector<T>& v) {
 ^
test.cpp:9:1: note:   template argument deduction/substitution failed:
test.cpp:15:16: note:   mismatched types ‘const std::vector<T>’ and ‘const int’
         print(e);
                ^

你知道怎么解决这个问题吗?

有许多简洁的解决方案,但有一个非常接近您的解决方案,没有重复,没有任何太聪明的东西,没有任何库函数,下面是

template <typename T>
void print_container(const T&);
template <typename T>
void print(const std::vector<T>& v) { print_container(v); }
template <typename T>
void print(const std::list<T>& l) { print_container(l); }
template <typename T>
void print(const T& e) { cout << e; }
template <typename T>
void print_container(const T& c) {
    cout << "[";
    bool isFirst = true;
    for (const auto& e : c) {
        if (isFirst) isFirst = false;
        else cout << ",";
        print(e);
    }
    cout << "]";
}

也许您应该遵循for_each算法的模式。点击链接查看如何定义该算法的示例。http://www.cplusplus.com/reference/algorithm/for_each/

如果你想要一个泛型的打印机,那么你应该倾向于使用迭代器作为算法的输入。那么,由哪个容器提供它们就没有区别了,你的函数甚至可以接受指向C数组的指针。更进一步,如果你想让它为用户定义类型工作,那么用户定义类型应该有重载流操作符来支持它们。

也看看这个,并考虑更多的选择。http://www.cplusplus.com/reference/iterator/ostream_iterator/

我不能在评论中发布这个,但这里是另一个答案的简化版本,其中包含一个主要用于测试。测试网址:http://www.compileonline.com/compile_cpp11_online.php

当然,您可能需要对其他类型(如双精度类型或用户定义类型)进行专门化。

#include <vector>
#include <list>
#include <iostream>
template <typename T>
void print_container(const T&);
template <typename T>
void print(const T& e) { std::cout << e; }
template <typename T>
void print_container(const T& c) {
    std::cout << "[";
    bool isFirst = true;
    for (const auto& e : c) {
        if (isFirst) isFirst = false;
        else std::cout << ",";
        print(e);
    }
    std::cout << "]";
}
int main()
{
    std::vector<int> v = {0, 1, 3, 5, 7, 9};
    std::list<int> l =  {0, 1, 3, 5, 7, 9};
    print_container(v); 
    print_container(l);
}