C++ 新手问题 - C++ 编译器如何知道模板函数的参数具有 STL 方法作为成员?在 C# 中,您通常会告诉泛型方法参数具有类型约束。它必须实现一个接口(interface),但使用 C++ 模板对参数类型没有限制。
#include <list>
#include <iostream>
using namespace std;
template <typename T>
void DisplayContents (const T& Input)
{
for (auto iElement = Input.cbegin() // no intellisense
; iElement != Input.cend()
; ++ iElement )
cout << *iElement << ' ';
cout << endl;
}
int main ()
{
std::list <int> listIntegers;
listIntegers.push_front (10);
listIntegers.push_front (2011);
listIntegers.push_back (-1);
listIntegers.push_back (9999);
DisplayContents(listIntegers);
// DisplayContents(99); // neither of these will compile
// DisplayContents(new string("")); //
return 0;
}
因此,在模板化方法 DisplayContents<>(const T& Input) 中,输入没有智能感知。当您键入句点字符时,不会弹出任何建议(这并不奇怪,因为函数参数未指定输入必须是列表或任何其他类型的 STL 容器)。
但是,如果您尝试将不是 STL 容器的内容发送到 DisplayContents<>(const T& Input),则编译器会抛出以下错误:-
- 错误 C2100:非法间接寻址
- 错误 C2228:'.cbegin' 的左边必须有类/结构/union
- error C3536: 'iElement': 在初始化之前无法使用
表明编译器确实知道需要具有一些基本特征的参数类型。
谁能解释一下编译器如何“知道”当列表作为参数发送时可以使用 cbegin() 和 * 运算符,而不是当发送字符串或 int 时,显然类型不是被称为 intellisense 的方法没有采用 cbegin() 方法?
最佳答案
其实很简单。编译器会假设 T
是您传入的参数类型,然后继续编译。如果它遇到任何错误,那么它会报告这些错误。只要您使用的参数类型会有效,如果您对该类型进行硬编码,那么它就会有效。
在您的情况下,它因 int 而失败,因为 int 没有 cbegin()
方法。
它以 new std::string("")
失败,因为参数类型变成了 std::string * const &
,你不能调用 .cbegin()
在这个指针上。 (您必须改为调用 ->cbegin()
。)
但是,您可以使用 std::string("")
调用它(注意缺少 new
),这将导致参数为 const std::string &
,这将编译。
因此它与编译器“知道 T
表示标准容器”完全无关。如果您使用 cbegin()
和 cend()
方法创建一个简单类型,并确保这些方法的返回值可以递增、取消引用和比较是否相等,这种类型也可以。
(使用用户定义类型的模板函数的 Here is a demo。)
关于c++编译器如何知道参数是STL容器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26717837/