【问题标题】:What's the correct syntax for a member function of a class template returning a type defined in that class?类模板的成员函数返回该类中定义的类型的正确语法是什么?
【发布时间】:2011-03-24 16:47:48
【问题描述】:

我目前正在学习 Accelerated C++,我被困在练习 11-6 上。这个想法是将标准库向量重新实现为一个名为 Vec 的类。

我在使用 iterator erase(iterator) 成员时遇到问题,因为在类定义之外我不知道正确的语法,而且我尝试的所有操作都会导致编译器错误。我目前拥有的代码是:

template <class T> T* Vec<T>::erase(T* pos){

    if(pos < avail)
        std::copy(pos + 1, avail, pos);

    --avail;
    alloc.destroy(avail);

    return pos;

}

这非常有效。但是,为了可维护性和与 stl 中算法的兼容性,我知道我应该这样做:

template <class T> Vec<T>::iterator Vec<T>::erase(Vec<T>::iterator pos){

    // As before

}

我已经在类定义中定义了iterator,如下:

 typedef T* iterator;

尝试用第二个代码 sn -p 编译结果:

D:\Documents\Programming\Accelerated C++\Chapter 11>cl /EHsc Vec.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

Vec.cpp
Vec.cpp(23) : warning C4346: 'Vec<T>::iterator' : dependent name is not a type prefix with 'typename' to indicate a type
Vec.cpp(23) : error C2143: syntax error : missing ';' before 'Vec<T>::erase'
Vec.cpp(23) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Vec.cpp(23) : fatal error C1903: unable to recover from previous error(s); stopping compilation

遗憾的是,该警告对我来说没有多大意义,在阅读了 MSDN page for it 之后,我无法确切地看到它会如何应用于我的代码。

其余消息似乎编译器无法识别返回类型。

我尝试了许多不同的组合,但搜索并不是很有帮助。我将不胜感激任何帮助。谢谢!

【问题讨论】:

  • 如果您仔细观察,第一条编译器消息会显示“带有typename 的前缀以指示类型”。现在你知道这意味着什么了!
  • 这是有道理的。我敢肯定,在“不是一种类型”之后的一段时间会帮助我弄清楚这一点。

标签: c++ templates stl


【解决方案1】:
  template <class T> 
  typename Vec<T>::iterator Vec<T>::erase(typename Vec<T>::iterator pos){
 //^^^^^^^^ note this                      ^^^^^^^^ note this as well!

       //your code!
  }

也就是说,typename 在两个地方是必需的。因为iterator是依赖名,所以typename是必须的!

在 Stackoverflow 上阅读一位名叫 Johannes 的好人的精彩解释:

看完后你也可以看这个话题:


其他好文章的链接:

【讨论】:

  • 谢谢,效果很好。我现在会做一些阅读,所以我可以更好地理解为什么
  • @usm:我发布了一些链接。阅读约翰内斯的解释。他的解释很好,比你在网上找到的要好得多!
【解决方案2】:
template <class T> typename Vec<T>::iterator Vec<T>::erase(typename Vec<T>::iterator pos){

    // As before

}

... 因为这里的迭代器是 dependent on template parameter" 没有typename 编译器假装认为 Vec::iterator 是 Vec 的静态成员 :)

【讨论】:

  • tyepname 在参数中也是必需的!
猜你喜欢
  • 2014-05-05
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多