【问题标题】:Templates, nested classes, and "expected constructor, destructor, or conversion before '&' token"模板、嵌套类和“'&' 标记之前的预期构造函数、析构函数或转换”
【发布时间】:2010-12-16 01:24:18
【问题描述】:

在使用一些模板并为自己编写一个带有迭代器的基本容器类时,我发现自己需要将成员函数的主体从模板类移动到一个单独的文件中以符合样式指南。但是,我遇到了一个有趣的编译错误:

runtimearray.cpp:17:错误:预期 构造函数、析构函数或类型 '&' 标记之前的转换 runtimearray.cpp:24:错误:预期 构造函数、析构函数或类型 '&' 标记之前的转换 runtimearray.cpp:32:错误:预期 构造函数、析构函数或类型 '&' 标记之前的转换 runtimearray.cpp:39:错误:预期 构造函数、析构函数或类型 '&' 标记之前的转换 runtimearray.cpp:85:错误:预期 构造函数、析构函数或类型 'RuntimeArray' 之前的转换 runtimearray.cpp:91:错误:预期 构造函数、析构函数或类型 'RuntimeArray' 之前的转换

runtimearray.h:

#ifndef RUNTIMEARRAY_H_
#define RUNTIMEARRAY_H_

template<typename T>
class RuntimeArray
{
 public:
  class Iterator
  {
    friend class RuntimeArray;
   public:
    Iterator(const Iterator& other);

    T& operator*();
    Iterator& operator++();
    Iterator& operator++(int);
    Iterator& operator--();
    Iterator& operator--(int);
    bool operator==(Iterator other);
    bool operator!=(Iterator other);

   private:
    Iterator(T* location);

    T* value_;
  };

  RuntimeArray(int size);
  ~RuntimeArray();

  T& operator[](int index);

  Iterator Begin();
  Iterator End();

 private:
  int size_;
  T* contents_;
};

#endif  // RUNTIMEARRAY_H_

runtimearray.cpp:

#include "runtimearray.h"

template<typename T>
RuntimeArray<T>::Iterator::Iterator(const Iterator& other)
    : value_(other.value_)
{
}

template<typename T>
T& RuntimeArray<T>::Iterator::operator*()
{
  return *value_;
}

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator++()
{
  ++value_;
  return *this;
}

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator++(int)
{
  Iterator old = *this;
  ++value_;
  return old;
}

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator--()
{
  --value_;
  return *this;
}

template<typename T>
RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator--(int)
{
  Iterator old = *this;
  --value_;
  return old;
}

template<typename T>
bool RuntimeArray<T>::Iterator::operator==(Iterator other)
{
  return value_ == other.value_;
}

template<typename T>
bool RuntimeArray<T>::Iterator::operator!=(Iterator other)
{
  return value_ != other.value_;
}

template<typename T>
RuntimeArray<T>::Iterator::Iterator(T* location)
    : value_(location)
{
}

template<typename T>
RuntimeArray<T>::RuntimeArray(int size)
    : size_(size),
      contents_(new T[size])
{
}

template<typename T>
RuntimeArray<T>::~RuntimeArray()
{
  if(contents_)
    delete[] contents_;
}

template<typename T>
T& RuntimeArray<T>::operator[](int index)
{
  return contents_[index];
}

template<typename T>
RuntimeArray<T>::Iterator RuntimeArray<T>::Begin()
{
  return Iterator(contents_);
}

template<typename T>
RuntimeArray<T>::Iterator RuntimeArray<T>::End()
{
  return Iterator(contents_ + size_);
}

我怎样才能消除这些错误?这些文件对我来说很有意义,但可惜的是编译器的说法很重要。

【问题讨论】:

    标签: c++ templates nested-class


    【解决方案1】:

    这不会按您希望的方式工作。您的所有函数声明和定义必须出现在您定义 RuntimeArray 的 .h 文件中。你看到的错误可能是别的东西,也许是类型名的东西,但即使你可以让 RunTimeArray.cpp 单独编译,也没有人能够使用它。

    如果你真的必须将定义放在单独的文件中,#include 在 runtimearray.h 的末尾

    【讨论】:

    • 在 Charles Bailey 修复后,包括 .cpp 文件允许客户端程序正常工作。这不是 我会 这样做的方式,(哎呀,据我所知,标准库和 Boost 使用唯一的标头方法,)但这是老师想要的方式。
    • 您可能想向您的老师指出,这些类型的“外部模板”是非标准的,并且仅受少数编译器支持(而且有些编译器不支持)。
    • 外部模板?我将类的声明和定义都包含在使用文件中。这似乎就像我只是在一个文件中完成所有操作一样。
    【解决方案2】:

    我认为您缺少 typename 关键字。

    例如

    template<typename T>
    RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator++()
    

    应该是

    template<typename T>
    typename RuntimeArray<T>::Iterator& RuntimeArray<T>::Iterator::operator++()
    

    依赖于模板参数的“嵌套”类型需要typename 关键字来告诉编译器它们应该是类型,否则会产生歧义。

    【讨论】:

    • 第一个怎么模棱两可?我没看到。
    • 在编译器到达Iterator 时,它不知道T 将是什么,并且Iterator 依赖于-通过RuntimeArray 模板-在T 上。 Iterator 可能会为某些专业命名成员函数或数据成员。为了正确解析声明,需要告诉编译器它是带有typename 关键字的类型。因为您的类型是一个嵌套类,所以它不像在其他一些示例中那样明显为什么需要此规则。
    【解决方案3】:

    这是一个非常有趣的风格指南。一般来说,模板函数的定义必须在头文件中。这是几个小时前的:Splitting templated C++ classes into .hpp/.cpp files--is it possible?

    【讨论】:

    • 我知道。这是针对大学的,我不同意大多数风格指南的一半。但是,请意识到这不是作业的一部分,而是我为解决作业所做的事情。我们甚至还没有接触到指针、模板甚至类。
    猜你喜欢
    • 2011-12-04
    • 2010-12-12
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多