在SAFEARRAY上实现for-each

时间:2015-10-23 13:49:49

标签: c++ c++11 com

我之前没有实现过基于范围的机制,并且很好奇这对于SAFEARRAY是如何工作的。

可能的用例是希望从std::vector填充SAFEARRAY *。您是否需要将SAFEARRAY包装在提供特殊迭代器的自定义类中?

一个问题是SAFEARRAY可以包含不同的类型。假设你映射了字符串< - > BSTR,int< - > I4和所有其他类型无效,你怎么能设置像for(string s : MySafeArray)

这样的东西

我们已经有了一个包装类:template <class T> SafeArrayWrapper{...}其中T是您希望数组内容被视为的类型。

2 个答案:

答案 0 :(得分:2)

嗯,尊重从SAFEARRAY枚举字符串或整数的能力的最简单方法是创建两个集合类,一个用于表示字符串,另一个用于表示整数,用于安全阵列。

这可能代表一个可枚举的字符串集合。

class SafeArrayStringList {
public:
  SafeArrayStringList(SAFEARRAY);
  class iterator;
  iterator begin();
  iterator end();
};

对此至关重要的是迭代器的(前向)声明,以及a()和end()方法,当你在其中一个上使用基于for循环的范围时,C ++将会寻找。

迭代器的定义如下:

class SafeArrayStringList::iterator {
  SAFEARRAY _array;
  int _idx;
public:
  iterator(SAFEARRAY);
  iterator& operator++();
  bool operator!=(const iterator& rhs);
  std::string operator*();
};

这几乎是您所需要的(在XCode上)以满足基于for循环的范围的要求。

正确完成你应该让你的迭代器扩展std :: iterator类,但为了清楚起见,我已经删除了实际上并不需要的所有内容。

要枚举SAFEARRAY中的字符串

for(auto stringitem : SafeArrayStringList(safeArray){
  std::string foo = *stringitem;
} 

答案 1 :(得分:0)

您需要创建:

  1. 支持operator*operator++operator!=重载的迭代器。将其设为std::itertor

  2. 的子类型
  3. 函数begin(SAFEARRAY&)end(SAFEARRAy&)及其const版本。

  4. 这是一个人为的例子,展示了为用户定义的类型支持范围 - for所需的内容。

    #include <vector>
    #include <iterator>
    
    struct Foo
    {
       std::vector<int> vec_;
    };
    
    struct FooIterator : std::iterator<std::forward_iterator_tag, int>
    {
       FooIterator(Foo& f) : foo_(f), iter_(f.vec_.begin()) {}
       FooIterator& end() { iter_ = foo_.vec_.end(); return *this; }
    
       int& operator*() { return *iter_; }
       std::vector<int>::iterator operator++() { return ++iter_; }
       bool operator!=(FooIterator const& rhs) const { return iter_ != rhs.iter_; }
    
       Foo& foo_;
       std::vector<int>::iterator iter_;
    };
    
    FooIterator begin(Foo& foo)
    {
       return FooIterator(foo);
    }
    
    FooIterator end(Foo& foo)
    {
       return FooIterator(foo).end();
    }
    
    int main()
    {
       Foo foo;
       for ( auto f : foo )
       {
       }
    
       return 0;
    }