C++模板:返回列表::迭代器
我怎样才能使下面的代码工作?在编译期间,我收到一条错误消息,告诉我 searchForResource
函数没有返回类型。
template<class T>
class ResourceManager
{
private:
struct ResourceWrapper;
std::list<ResourceWrapper*> resources_; // This compiles fine
std::list<ResourceWrapper*>::iterator // Error occurs here
searchForResource(const std::string& file);
};
另外,这是我定义 searchForResource
函数的方式吗?
template<class t>
std::list<typename ResourceManager<T>::ResourceWrapper*>::iterator
ResourceManager<T>::searchForResource(const std::string& file)
{
// ...
}
How can I make the following code work? During compilation I get an error telling me that the searchForResource
function has no return type.
template<class T>
class ResourceManager
{
private:
struct ResourceWrapper;
std::list<ResourceWrapper*> resources_; // This compiles fine
std::list<ResourceWrapper*>::iterator // Error occurs here
searchForResource(const std::string& file);
};
Also, is this how I would define the searchForResource
function?
template<class t>
std::list<typename ResourceManager<T>::ResourceWrapper*>::iterator
ResourceManager<T>::searchForResource(const std::string& file)
{
// ...
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
std::list::iterator
编译器很难理解。在实现和声明中添加typename
前缀,让编译器知道它是一个类型。就像这样:
std::list<ResourceWrapper*>::iterator
is hard for the compiler to understand. Prefix it withtypename
in both the implementation and the declaration to let the compiler know that it's a type.Like so:
有一个经验法则可以避免此类编译错误。
每当您声明变量或函数时,使用模板后跟作用域解析运算符
::
,然后始终将关键字typename
放入定义前面。例如,
同样的事情也适用于函数声明。
There is a rule of thumb to avoid such compilation errors.
Whenever you are declaring a variable or function, with a template followed by scope resolution operator
::
then always put a keywordtypename
in front of the definition.For example,
Same thing is applicable to function declaration also.
我认为您缺少
typename
关键字。I think you're missing a
typename
keyword.问题是
ResourceWrapper
是一个依赖名称 *(它的定义取决于类型参数T
),这使得std: :列表< ResourceWrapper * >
依赖类型名称。模板分两遍检查,在第一遍期间,检查模板没有实际类型替换的正确性。现在,当您输入std::list< ResourceWrapper* >::iterator
编译器无法预先知道iterator
实际上是一种类型,而不是类std::list
的静态属性或成员。 ResourceWrapper* >
因为类型是相关的并且T
尚未被替换。您必须使用
typename
关键字来提示编译器,告知它iterator
确实是一种类型,正如其他人之前已经提到的:代码,我不能说,但似乎
ResourceWrapper
实际上不应该是T
上的依赖类型。如果它实际上是非依赖的,则应该将该类型移到类模板之外。在这种情况下,将不再需要typename
:因为它是在模板外部定义的,所以对于
ResourceManager
模板的所有可能实例化都有一个定义,现在< code>ResourceWrapper 不再依赖于T
,并且不再需要(也不正确)typename
。* 为什么依赖于
ResourceWrapper
以及这对代码有何影响。通过讨论完全限定名称,可以更容易地看出
ResourceWrapper
依赖于类型T
的原因:::ResourceManager::ResourceWrapper
。T
是类型的一部分,因此T
影响ResourceWrapper
的实际定义。这在某种程度上是一个人为的示例,您可以说,如果编译器正在解析此特定模板,那么它必须知道ResourceWrapper
是一种类型,因此std::list
std::list
ResourceWrapper*>::iterator
是一种类型...这就是问题所在。没有特别的理由不为ResourceManager
的特定实例化专门化std::list
模板:同样,这是人为的,但编译器不可能预先知道解析模板,在您实际使用特定类型实例化模板之前,不会出现这种专门化。
The problem is that
ResourceWrapper
is a dependent name *(it's definition depends on the type argumentT
), and that makesstd::list< ResourceWrapper * >
a dependent type name. Templates are checked in two passes, during the first pass, correctness of the template without actual type substitution is checked. Now when you typestd::list< ResourceWrapper* >::iterator
the compiler cannot know upfront thatiterator
is in fact a type and not an static attribute or member of the classstd::list< ResourceWrapper* >
because of the type being dependent and theT
not yet being substituted.You have to hint the compiler as to inform it that the
iterator
is indeed a type by using thetypename
keyword, as others have already mentioned before:Without seeing the rest of the code, I cannot say, but it seems as if
ResourceWrapper
should actually not be a dependent type onT
. If it is in fact non-dependent, you should move the type outside of the class template. in that case, thetypename
will no longer be required:Because it is defined outside of the template there is a single definition for all possible instantiations of the
ResourceManager
template, nowResourceWrapper
is no longer dependent onT
, andtypename
is no longer needed (nor correct).* Why is
ResourceWrapper
dependent and how could this affect the code.The reason that
ResourceWrapper
is dependent on the typeT
is easier seen by discussing the fully qualified name:::ResourceManager<T>::ResourceWrapper
. TheT
is part of the type, and as suchT
affects the actual definition ofResourceWrapper
. This is somehow a contrived example in that you can arguably say that if the compiler is parsing this particular template, then it must know thatResourceWrapper
is a type, and thus thatstd::list< ResourceWrapper*>::iterator
is a type... and here is the problem. There is no particular reason not to have an specialization of thestd::list
template for a particular instantiation ofResourceManager
:Again, contrived, but the compiler cannot possibly know upfront while parsing the template that such an specialization will not be present before you actually instantiate the template with a particular type.
您有 ResourceWrapper 结构的前向声明,这对于编译良好的行来说已经足够了,但是您收到错误,因为此时编译器需要 ResourceWrapper 结构的完整类型声明。 (可能是你的答案,这段代码实际上可以在 VS2008 上编译得很好)
you have forward declaration of ResourceWrapper struct which is good enough for the line that compiles fine, but you are getting the error because at that point compiler needs full type declaration for ResourceWrapper struct. (possibly your answer, this code actually compiles fine with VS2008)