简体   繁体   English

默认构造有效的输入迭代器

[英]Default Construction of valid Input Iterators

I am designing an input iterator type that enumerates all running processes in a system. 我正在设计一个输入迭代器类型,它枚举系统中所有正在运行的进程。

This is similar to an iterator I designed to enumerate modules in a process. 这类似于我设计用于枚举进程中的模块的迭代器。 The module iterator takes a 'process' object in the constructor, and a default constructed iterator is considered to be the off-the-end iterator. 模块迭代器在构造函数中采用“进程”对象,默认构造的迭代器被认为是非现实的迭代器。

Example: 例:

hadesmem::ModuleIterator beg(process);
hadesmem::ModuleIterator end;
assert(beg != end);

I do not know what to do about process enumeration though, because there is no 'state' or information that needs to be given to the iterator (everything is handled internally by the iterator using the Windows API). 我不知道如何处理进程枚举,因为没有“状态”或信息需要提供给迭代器(所有内容都由迭代器使用Windows API在内部处理)。

Example: 例:

// This is obviously a broken design, what is the best way to distinguish between the two?
hadesmem::ProcessIterator beg;
hadesmem::ProcessIterator end;

What is the idiomatic way to deal with this situation? 处理这种情况的惯用方法是什么? ie Where you need to distinguish between the creation of a 'new' iterator and an off-the-end iterator when nothing needs to be given to the iterator constructor. 即,当需要向迭代器构造函数提供任何内容时,您需要区分“新”迭代器和异端迭代器的创建。

If it's relevant, I am able to use C++11 in this library, as long as it's supported by VC11, GCC 4.7, and ICC 12.1. 如果它是相关的,我可以在这个库中使用C ++ 11,只要它得到VC11,GCC 4.7和ICC 12.1的支持。

Thanks. 谢谢。

EDIT: 编辑:

To clarify, I know that it's not possible to distinguish between the two in the form I've posted above, so what I'm asking is more of a 'design' question than anything else... Maybe I'm just overlooking something obvious though (wouldn't be the first time). 为了澄清,我知道我不可能在上面发布的形式中区分这两者,所以我要问的是更多的“设计”问题而不是其他任何东西......也许我只是忽略了一些东西虽然很明显(不是第一次)。

What you really want to do is create a kind of ProcessList object, and base the iterators on that. 你真正想要做的是创建一种ProcessList对象,并在其上建立迭代器。 I wouldn't want to be enumerating all processes or something every time I increment an iterator. 每次我增加迭代器时,我都不想枚举所有进程或其他东西。

If you create a class that holds the parameters that go into the CreateToolhelp32Snapshot() representing the snapshot you're iterating over, you'll have a natural factory for the iterators. 如果您创建一个类,该类包含进入CreateToolhelp32Snapshot()的参数,表示您正在迭代的快照,那么您将拥有一个用于迭代器的自然工厂。 Something like this should work (I'm not on Windows, so not tested): 这样的东西应该工作(我不在Windows上,所以没有测试):

class Process;
class Processes {
    DWORD what, who;
public:
    Processes(DWORD what, DWORD who) : what(what), who(who) {}

    class const_iterator {
        HANDLE snapshot;
        LPPROCESSENTRY32 it;
        explicit const_iterator(HANDLE snapshot, LPPROCESSENTRY32 it)
            : snapshot(snapshot), it(it) {}
    public:
        const_iterator() : snapshot(0), it(0) {}

        // the two basic functions, implement iterator requirements with these:
        const_iterator &advance() {
            assert(snapshot);
            if ( it && !Process32Next(snapshot, &it))
                it = 0;
            return *this;
        }
        const Process dereference() const {
            assert(snapshot); assert(it);
            return Process(it);
        }
        bool equals(const const_iterator & other) const {
            return handle == other.handle && it == other.it;
        }
    };

    const_iterator begin() const {
        const HANDLE snapshot = CreateToolhelp32Snapshot(what, who);
        if (snapshot) {
            LPPROCESSENTRY32 it;
            if (Process32First(snapshot, &it))
                return const_iterator(snapshot, it);
        }
        return end();
    }
    const_iterator end() const {
        return const_iterator(snapshot, 0);
    }
};

inline bool operator==(Processes::const_iterator lhs, Processes::const_iterator rhs) {
    return lhs.equals(rhs);
}
inline bool operator!=(Processes::const_iterator lhs, Processes::const_iterator rhs) {
    return !operator==(lhs, rhs);
}

Usage: 用法:

int main() {
    const Processes processes( TH32CS_SNAPALL, 0 );
    for ( const Process & p : processes )
        // ...
    return 0;
}

You could use the named constructor idiom . 您可以使用命名的构造函数idiom

class ProcessIterator
private:
    ProcessIterator(int) //begin iterator
    ProcessIterator(char) //end iterator
    //no default constructor, to prevent mistakes
public:
    friend ProcessIterator begin() {return ProcessIterator(0);}
    friend ProcessIterator end() {return ProcessIterator('\0');}
}

int main() {
    for(auto it=ProcessIterator::begin(); it!=ProcessIterator::end(); ++it)
        //stuff
}

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

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