简体   繁体   English

为什么以下模板化类成员函数无法编译?

[英]Why does the following templated class member function not compile?

The following code compiles even though nonexisting_func() doesn't exist.即使nonexisting_func()不存在,以下代码也会编译。 The code compiles because it's a member function of a templated class, but the function itself is not compiled because it's not being used in the program, correct?代码编译是因为它是模板化类的成员函数,但函数本身没有被编译,因为它没有在程序中使用,对吗? So you could have any syntax errors inside heapify_down and the entire code should still compile?所以你可能在heapify_down有任何语法错误并且整个代码仍然应该编译?

#include <iostream>
#include <vector>

template<typename T>
class heap
{
public:
   void heapify_down(std::vector<T> &vec)
   {
      nonexisting_func(vec);
   }
};

int main( ) 
{ 
   heap<int> my_heap;
   return 0;
}

If my understanding above is correct, then why does the following code not compile?如果我上面的理解是正确的,那么为什么下面的代码不能编译?

#include <iostream>
#include <vector>

template<typename T>
class heap
{
public:
   void heapify_down(std::vector<T> &vec)
   {
      a;
      nonexisting_func(vec);
   }
};

int main( ) 
{ 
   heap<int> my_heap;
   return 0;
}

Compiling this code gives me the error error: use of undeclared identifier 'a' .编译此代码给了我错误error: use of undeclared identifier 'a' Why is it trying to compile the heapify_down() function now?为什么它现在试图编译heapify_down()函数?

Template code basically has two passes that it goes through.模板代码基本上有两遍。 The first pass just looks at the code and makes sure that it is syntactically correct, and that any non-dependent code is correct.第一遍只是查看代码并确保它在语法上是正确的,并且任何非依赖代码都是正确的。 By non-dependent code, I mean code that does not depend on the template parameter(s).非依赖代码是指不依赖于模板参数的代码。

After that there is a second pass that happens after the template is actually instantiated.之后,在实际实例化模板之后会发生第二次传递。 At that point there is no more dependent code as all the template parameters are known and the compiler can exam the code like it would for any non-template code.那时没有更多的依赖代码,因为所有模板参数都是已知的,编译器可以像检查任何非模板代码一样检查代码。

In

void heapify_down(std::vector<T> &vec)
{
    nonexisting_func(vec);
}

The call to nonexisting_func depends on vec because of ADL and vec depends on T so it's compilation is deferred.要将呼叫nonexisting_func取决于vec因为ADLvec取决于T所以它的编译推迟。 It is syntactically correct so it wont have any further checking done until it is instantiated.它在语法上是正确的,因此在实例化之前不会进行任何进一步的检查。 If you changed main to如果您将 main 更改为

int main( ) 
{ 
   std::vector<int> foo;
   heap<int> my_heap;
   my_heap.heapify_down(foo);
   return 0;
}

So that heapify_down is actually instantiated then you would get a compiler error like所以heapify_down实际上是实例化的,那么你会得到一个编译器错误,比如

main.cpp:22:7: error: use of undeclared identifier 'nonexisting_func'
      nonexisting_func(vec);
      ^
main.cpp:30:12: note: in instantiation of member function 'heap<int>::heapify_down' requested here
   my_heap.heapify_down(foo);
           ^
1 error generated.

You would also get an error using你也会得到一个错误使用

void heapify_down(std::vector<T> &vec)
{
    ::nonexisting_func(vec);
}

Because now we are no longer have an unqualified name so ADL is ignored meaning ::nonexisting_func is no longer a dependent name.因为现在我们不再有一个不合格的名称,所以 ADL 被忽略,这意味着::nonexisting_func不再是一个依赖名称。

With

void heapify_down(std::vector<T> &vec)
{
   a;
   nonexisting_func(vec);
}

a doesn't depend on T so the compiler tries to look it up. a不依赖于T因此编译器会尝试查找它。 It can't find it, so you get an error.它找不到它,所以你得到一个错误。 If you had instead done如果你做了

void heapify_down(std::vector<T> &vec)
{
   this->a;
   nonexisting_func(vec);
}

then again you would not get an error until you instantiate the function since a now depends on this and this depends on T .然后再次在实例化函数之前不会出现错误,因为a now 取决于thisthis取决于T

The key point here is that nonexisting_func(vec);这里的关键点是nonexisting_func(vec); is going to mean something different depending on what T is (since vec is a vector<T> ).将意味着不同的东西,具体取决于T是什么(因为 vec 是一个vector<T> )。

So in that case, the compiler cannot try to resolve the call to nonexisting_func() immediately as it lexes the function, and can only do so when comes the time to instantiate the template (which you never do).因此,在这种情况下,编译器无法在对函数进行词法分析时立即尝试解析对nonexisting_func()的调用,并且只能在实例化模板的时候这样做(您永远不会这样做)。

In the case of a , since that identifier doesn't depend on anything, the compiler should perform the lookup immediately.在的情况下a ,因为该标识符不依赖于任何东西,编译器应该立即进行查找。 I say should because MSVC in particular tends to still delay the lookup until instantiation, even though it shouldn't on paper.我说应该是因为 MSVC 特别倾向于将查找延迟到实例化,即使它不应该在纸上。

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

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