【发布时间】:2014-11-03 15:51:45
【问题描述】:
c++ 新手问题 - C++ 编译器如何知道模板函数的参数有 STL 方法作为成员?在 C# 中,您告诉泛型方法参数具有类型约束,这是最常见的。它必须实现一个接口,但使用 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) 中,Input 没有智能感知。当您键入句点字符时,不会弹出任何建议(这并不奇怪,因为函数参数没有指定输入必须是列表或任何其他类型的 STL 容器)。
但是,如果您尝试将不是 STL 容器的内容发送到 DisplayContents(const T& Input),那么编译器会抛出以下错误:-
- 错误 C2100:非法间接
- 错误 C2228:'.cbegin' 左侧必须有类/结构/联合
- error C3536: 'iElement': 在初始化之前不能使用
暗示编译器确实知道需要具有一些基本特征的参数类型。
任何人都可以解释一下编译器如何“知道” cbegin() 和 * 运算符可以在作为参数发送列表时使用,而不是在发送字符串或 int 时,显然类型不是被称为智能感知没有采用 cbegin() 方法?
【问题讨论】:
-
代码实例化后才知道。它尝试使用您提供的任何模板参数来实例化函数体,然后如果函数实际上不是该类型的有效成员,则会给您一个错误。在相关说明中,您可能需要查看 Concepts,这是 C++ 即将推出的功能,它允许您对模板类型提出要求。
-
补充一点:Intellisense 不能这样做,因为它不检查哪些类型被传递给函数。首先,这很困难,因为它必须查看项目中函数的每个实例化并找到它们成员的交集(并且假设所有实例化都提供正确的类型)。其次,在许多情况下这是不可能的,例如在库头中,您根本无法分辨可能传递的每一种类型。但是,它可以在编译时完成,因为要编译代码,我们必须实例化它。
标签: c++ templates intellisense