简体   繁体   English

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

[英]c++ How does compiler know that a parameter is an STL container?

c++ newbie question - How can the C++ compiler know that the parameter to a template function has has STL methods as members? c ++新手问题-C ++编译器如何知道模板函数的参数具有STL方法作为成员? in C# you tell a generic method that a parameter has a type constraint, most commonly. 在C#中,您通常会告诉通用方法参数具有类型约束。 it must implement an interface, but with c++ templates there is no restriction on the parameter type. 它必须实现一个接口,但是对于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;
}

so, in the templated method DisplayContents<>(const T& Input) , there is no intellisense on Input. 因此,在模板化方法DisplayContents <>(const T&Input)中,Input上没有智能感知。 When you type the period character, no suggestions pop up (which isn't that suprising since the function parameter hasn't specified that the input must be a list or any other type of STL container). 键入句点字符时,不会弹出任何建议(这并不令人惊讶,因为function参数尚未指定输入必须是列表或任何其他类型的STL容器)。

However, if you try and send something that isn't an STL container into DisplayContents<>(const T& Input), then the compiler throws these errors:- 但是,如果您尝试将不是STL容器的内容发送到DisplayContents <>(const T&Input),则编译器将引发以下错误:

  • error C2100: illegal indirection 错误C2100:非法间接
  • error C2228: left of '.cbegin' must have class/struct/union 错误C2228:“。cbegin”的左侧必须具有class / struct / union
  • error C3536: 'iElement': cannot be used before it is initialized 错误C3536:'iElement':在初始化之前无法使用

suggesting that the compiler does know something about the type of the parameter needing to have some basic characteristics. 建议编译器确实了解需要具有一些基本特征的参数类型。

Can anyone please explain how the compiler "knows" that cbegin() and * operator can be used when a list is sent as the parameter, but not when a string or an int is sent, when apparently the type isn't known as intellisense isn't picking up the method cbegin() ? 任何人都可以解释一下当列表作为参数发送时,编译器如何“知道”可以使用cbegin()和*运算符,但是当字符串或int发送时(显然不是该类型称为intellisense)时,编译器如何“知道”不使用方法cbegin()吗?

It's quite simple, really. 确实很简单。 The compiler will pretend that T is the type of argument you passed in and then proceed with compilation. 编译器会假装T是您传入的参数类型,然后继续进行编译。 If it runs into any errors then it will report those. 如果遇到任何错误,则将报告这些错误。 As long as the type of argument you use would work if you hard-coded that type then it will work. 只要你使用,如果你硬编码的类型工作参数的类型,那么它工作。

In your case, it fails with int because an int has no cbegin() method. 在您的情况下,由于int没有cbegin()方法,因此int失败。

It fails with new std::string("") because the argument type becomes std::string * const & , and you can't call .cbegin() on this pointer. 由于new std::string("")失败,因为参数类型变为std::string * const & ,并且您无法在此指针上调用.cbegin() (You would have to call ->cbegin() instead.) (您必须调用->cbegin() 。)

However, you can call it with std::string("") (note the lack of new ) which will cause the argument to be const std::string & , and this will compile. 但是,您可以使用std::string("")调用它(注意缺少new ),这将导致参数为const std::string & ,并且可以编译。

So it has nothing at all to do with the compiler "knowing that T represents a standard container." 因此,它与编译器“知道T代表标准容器”完全无关。 If you create a simple type with cbegin() and cend() methods and make sure that the return values from those methods can be incremented, dereferenced, and compared for equality, that type would work just as well. 如果你创建一个简单的类型与cbegin()cend()方法,并确保从这些方法的返回值可以增加,废弃时,和平等相比,该类型将工作一样好。

( Here is a demo of your template function working with a user-defined type.) 这是使用用户定义类型的模板函数的演示 。)

Template used to make generic code. 用于制作通用代码的模板。

And here the compiler will generate three overload functions for you. 在这里,编译器将为您生成三个重载函数。

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

obviously version 2 and 3 won't compile, type const int& and string* const& does not have method cbegin() nor cend() 显然版本2和3无法编译,类型const int&string* const&没有方法cbegin()或cend()

PS: version 3 param should be string* const& Input , thanks to cdhowie PS:由于cdhowie,版本3参数应该为string* const& Input

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM