C++ 如何创建操作员->;在没有容器的迭代器中? 模板 类枚举迭代器{ 公众: 常量枚举*运算符->()常量{ return&(Enum::OfInt(i));//警告:正在获取临时 } 常量枚举运算符*()常量{ 返回Enum::OfInt(i);//这个没有问题! } 私人: int i; };

C++ 如何创建操作员->;在没有容器的迭代器中? 模板 类枚举迭代器{ 公众: 常量枚举*运算符->()常量{ return&(Enum::OfInt(i));//警告:正在获取临时 } 常量枚举运算符*()常量{ 返回Enum::OfInt(i);//这个没有问题! } 私人: int i; };,c++,pointers,iterator,C++,Pointers,Iterator,我得到上面的警告。目前,我正在使用此黑客: template <class Enum> class EnumIterator { public: const Enum* operator-> () const { return &(Enum::OfInt(i)); // warning: taking address of temporary } const Enum operator* () const { return Enum:

我得到上面的警告。目前,我正在使用此黑客:

template <class Enum>
class EnumIterator {
 public:

  const Enum* operator-> () const {
    return &(Enum::OfInt(i));  // warning: taking address of temporary
  }

  const Enum operator* () const {
    return Enum::OfInt(i);     // There is no problem with this one!
  }

 private:
  int i;
};
模板
类枚举迭代器{
公众:
常量枚举*运算符->(){
tmp=Enum::OfInt(i);
返回&tmp;
}
私人:
int i;
Enum tmp;
};
但这很难看,因为迭代器充当丢失的容器

迭代值范围的正确方法是什么

更新: 迭代器专用于支持命名静态构造函数OFIT(代码段更新)的特定集合对象

请不要挑剔我粘贴的代码,只是要求澄清。我试着提取一个简单的片段

如果您想知道T将是强枚举类型(本质上是打包到类中的int)。将有typedef EnumIterator迭代器;在类EnumX内部

更新2: 添加的常量表示将通过->访问的强枚举类的成员不更改返回的临时枚举


使用运算符*更新了代码,没有问题。

迭代器在特定容器上进行迭代。实现取决于它是什么类型的容器。返回的指针应指向该容器的成员。您不需要复制它,但您确实需要跟踪您正在迭代的容器,以及您所在的位置(例如向量的索引),这可能是在迭代器的构造函数中初始化的。或者只使用STL。

有很多种迭代器

例如,在向量上,迭代器通常是普通指针:

template <class Enum>
class EnumIterator {
 public:
  const Enum* operator-> () {
    tmp = Enum::OfInt(i);
    return &tmp;
  }
 private:
  int i;
  Enum tmp;
};
模板
类迭代器
{
公众:
T*运算符->(){返回m_指针;}
私人:
T*m_指针;
};
但这是可行的,因为向量实际上只是一个数组

在双链接列表上,情况会有所不同,该列表将由节点组成

template <class T>
class Iterator
{
public:
  T* operator->() { return m_pointer; }

private:
  T* m_pointer;
};
模板
结构体类型
{
节点*m_prev;
Node*m_next;
T m_值;
};
模板
类迭代器
{
公众:
T*运算符->(){返回m_节点->m_值;}
私人:
节点*m_节点;
};
通常,您希望迭代器尽可能轻,因为迭代器是通过值传递的,所以指向底层容器的指针是有意义的

您可能需要添加额外的调试功能:

  • 使迭代器无效的可能性
  • 射程检查可能性
  • 容器检查(即,在比较引用同一容器的两个迭代器时进行检查)
但这些都是细节,首先,这有点复杂

请注意,这有助于锅炉板代码

编辑:(更新1和2分组)

在你的例子中,如果你的迭代器只是一个int,你不需要更多。事实上,对于强枚举,甚至不需要迭代器,只需要运算符++和运算符--:)

对容器进行引用的目的通常是实现那些++和--运算符。但是从您的元素开始,只要有一个int(假设它足够大),以及一种获取上一个和下一个值的方法就足够了


不过,如果您有一个静态向量,那么就可以简单地重用向量迭代器。

它返回什么?在这种情况下,它似乎返回了错误的类型。它应该返回一个T*,而似乎是返回一个T值,然后取它的地址。这可能会产生不正确的行为,因为它将丢失通过->进行的任何更新

template <class T>
struct Node
{
  Node* m_prev;
  Node* m_next;
  T m_value;
};

template <class T>
class Iterator
{
public:
  T* operator->() { return m_node->m_value; }

private:
  Node<T>* m_node;
};
问题不在于它丑陋,而在于它不安全。发生了什么,例如在如下代码中:

Enum* operator-> () {
  tmp = Enum::OfInt(i);
  return &tmp;
}
现在
g()
以两个指针结束,这两个指针都指向同一个内部临时对象,该内部临时对象应该是迭代器的实现细节。如果
g()
通过一个指针写入,则另一个值也会更改。哎哟

你的问题是,这个函数应该返回一个指针,但是你没有指向的对象。不管怎样,你都必须解决这个问题

我认为有两种可能性:

  • 因为这个东西似乎包装了一个
    枚举
    ,并且枚举类型没有成员,所以
    操作符->
    无论如何都是无用的(除非调用它,否则它不会被实例化,并且不能被调用,因为这将导致编译时错误),并且可以安全地忽略它
  • 在迭代器中存储一个正确类型的对象(类似于
    Enum::Enum_type
    ),仅当您希望对其执行类似整数的操作(例如,增量)时,才将其转换为
    int

    由于没有容器,我决定将迭代器合并到我的强枚举中。 我将raw int初始化为-1,以支持空枚举(limit==0),并能够将正则for循环与TryInc一起使用

    代码如下:

    void f(EnumIterator it)
    {
       g(*it, *it);
    }
    
    模板
    类枚举{
    公众:
    静态常数kLimit=极限;
    枚举():原始(-1){
    }
    bool TryInc(){
    if(原始+1原始=原始;
    }
    raw的静态枚举(uint raw){
    返回枚举(原始);
    }
    布尔运算符==(常量枚举和其他)常量{
    返回this->raw==other.raw;
    }
    布尔运算符!=(常量枚举和其他)常量{
    返回此->原始!=其他.raw;
    }
    受保护的:
    显式枚举(uint raw):原始(raw){
    }
    私人:
    未加工的;
    };
    
    用法:

    template <uint limit>
    class Enum {
     public:
      static const uint kLimit = limit;
    
      Enum () : raw (-1) {
      }
    
      bool TryInc () {
        if (raw+1 < kLimit) {
          raw += 1;
          return true;
        }
        return false;
      }
    
      uint GetRaw() const {
        return raw;
      }
    
      void SetRaw (uint raw) {
        this->raw = raw;
      }
    
      static Enum OfRaw (uint raw) {
        return Enum (raw);
      }
    
      bool operator == (const Enum& other) const {
        return this->raw == other.raw;
      }
    
      bool operator != (const Enum& other) const {
        return this->raw != other.raw;
      }
    
     protected:
      explicit Enum (uint raw) : raw (raw) {
      }
    
     private:
      uint raw;
    };
    
    类颜色:公共枚举{
    公众:
    静态常数为红色;
    //构造函数应自动转发。。。
    颜色():枚举(){
    }
    私人:
    颜色(uint原始):枚举(原始){
    }
    };
    常量颜色::红色=
    
    class Color : public Enum <10> {
     public:
      static const Color red;
    
      // constructors should be automatically forwarded ...
      Color () : Enum<10> () {
      }
    
     private:
    
      Color (uint raw) : Enum<10> (raw) {
      }
    };
    
    const Color Color::red = Color(0);
    
    
    int main() {
      Color red = Color::red;
    
      for (Color c; c.TryInc();) {
        std::cout << c.GetRaw() << std::endl;
      }
    }