C++模板:如何使用2个类型名,而只有一个是函数的输入?

问题描述 投票:0回答:2

下面是一段简单的代码。

#include <algorithm>
#include <iostream>
#include <iterator>
#include <unordered_map>
#include <vector>
using namespace std;

static void print(const vector<int>& v) {
    copy(
        begin(v),
        end(v),
        ostream_iterator<int>{cout, ", "}
    );
    cout << endl;
}

int main() {
    vector<pair<int, string>> v {1, 2, 3, 4, 5};

    cout << endl << "In vector:" << endl;
    print(v);

    return 0;
}

我试着使用模板编程来打印,因为我想通用化 container 是任何类型(vector, map, list等),元素也可以是任何类型的元素(int, double等)。)

template <typename C, typename T>
static void print(const C& container) {
    copy(
        begin(container),
        end(container),
        ostream_iterator<T>{cout, ", "}
    );
    cout << endl;
}

但是,它不会编译。

In function 'int main()':
prog.cc:31:12: error: no matching function for call to 'print(std::vector<int>&)'
   31 |     print(v);
      |            ^
prog.cc:18:13: note: candidate: 'template<class C, class T> void print(const C&)'
   18 | static void print(const C& container) {
      |             ^~~~~
prog.cc:18:13: note:   template argument deduction/substitution failed:
prog.cc:31:12: note:   couldn't deduce template parameter 'T'
   31 |     print(v);
      |            ^

我猜测是类型名 T 不是通过函数明确输入 print()确切地说,它的名字是 ostream_iterator<int>{cout, ", "} 哪个编译器不知道如何推断它的类型(为什么?)。

我想知道如何将两个类型名(CT)成 print() 函数,尽管只有类型名 C 是输入?

c++ templates copy ostream
2个回答
3
投票

你需要指定类型 T 明确地调用 print (例如 print(v, int),或者你写 print 以使其导出容器本身的值类型。通常的方法是使用 typename C::value_type,它存在于所有标准容器中。

template <typename C>
void print(const C& container) {
    using T = typename C::value_type;
    copy(
        begin(container),
        end(container),
        ostream_iterator<T>{cout, ", "}
    );
    cout << endl;
}

如果你不喜欢这种方式,或者你的容器可能并不总是有一个... ... value_type 成员,那么你可以很容易地直接导出值类型。

template <typename C>
void print(const C& container) {
    using T = std::remove_const_t<decltype(*std::cbegin(container))>;
    copy(
        std::cbegin(container),
        std::cend(container),
        ostream_iterator<T>{cout, ", "}
    );
    cout << endl;
}

2
投票

你不需要指定第二个模板参数。大多数STL容器都有一个成员 value_type 就是为了这个目的。所以你的功能需要是。

template <typename C, typename T = typename C::value_type>
static void print(const C& container) {
    copy(
        begin(container),
        end(container),
        ostream_iterator<T>{cout, ", "}
    );
    cout << endl;
}
© www.soinside.com 2019 - 2024. All rights reserved.