c ++编译器如何知道参数是STL容器?

时间:2014-11-03 15:51:46

标签: c++ templates intellisense

c ++ newbie question - 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&lt;&gt;(const T&amp; Input)中,输入上没有智能感知。当您键入句点字符时,不会弹出任何建议(由于函数参数未指定输入必须是列表或任何其他类型的STL容器,因此并不令人惊讶。)

但是,如果您尝试将不是STL容器的内容发送到DisplayContents&lt;&gt;(const T&amp; Input),那么编译器会抛出这些错误: -

  • 错误C2100:非法间接
  • 错误C2228:左边的&#39; .cbegin&#39;必须有class / struct / union
  • 错误C3536:&#39; iElement&#39;:在初始化之前无法使用

建议编译器确实知道需要具有某些基本特征的参数类型。

任何人都可以解释编译器&#34;如何知道&#34;当列表作为参数发送时,可以使用cbegin()和*运算符,但是当发送字符串或int时,可以使用cbegin()和*运算符,当显然类型不被称为intellisense时,不会选择方法cbegin()?

2 个答案:

答案 0 :(得分:6)

这很简单,真的。编译器将假装T是您传入的参数类型,然后继续编译。如果它遇到任何错误,那么它将报告这些错误。只要您使用的参数类型,如果您对该类型进行了硬编码,那么它工作。

在你的情况下,它因int而没有cbegin()方法而失败。

它因{1}}而失败,因为参数类型变为new std::string(""),您无法在此指针上调用std::string * const &。 (你必须改为调用.cbegin()。)

但是,你可以->cbegin()(注意缺少std::string(""))来调用它,这将导致参数为new,这将编译

所以它与编译器没有任何关系&#34;知道const std::string &代表一个标准容器。&#34;如果使用Tcbegin()方法创建一个简单类型,并确保这些方法的返回值可以递增,取消引用并进行相等性比较,那么该类型也可以正常工作。

(模板函数的Here is a demo使用用户定义的类型。)

答案 1 :(得分:0)

用于制作通用代码的模板。

此处编译器将为您生成三个重载函数。

void DisplayContents (const std::list<int>& Input)
void DisplayContents (const int& Input)
void DisplayContents (string* const & Input)

显然版本2和3不会编译,键入const int&string* const&没有方法cbegin()也没有cend()

PS:版本3 param应为string* const& Input,感谢cdhowie