直接在foreach循环中投射

时间:2014-03-28 13:27:31

标签: c++ c++11 foreach casting

在某种情况下,我有std::vector指向ClassA的指针。另一个类ClassB继承自ClassA。在某些时候我知道这个向量only包含指向ClassB实例的指针。我使用foreach loop迭代向量,然后将cast对象转换为ClassB。

目前看起来与此类似:

Class ClassA
{
}

Class ClassB : public ClassA
{
public:
    void DoSomething();
}

std::vector<ClassA*> vecA;

void iterate()
{
    for(ClassA* obj : vecA)
    {
        ((ClassB*)obj)->DoSomething();
    }
}

我想知道我是否可以在foreach循环中直接转换对象。这会更短,并且每次我想要使用它时都不需要我施放物体。我正在寻找看起来像这样的东西:

void iterate()
{
    for((ClassB*)ClassA* obj : vecA)
    {
        obj->DoSomething();
    }
}

这可能吗?如果不是,那么什么是一种简单的方法来节省&#39;演员,如果我想多次使用演出的对象?

提前致谢。

2 个答案:

答案 0 :(得分:3)

void iterate() {
  for(ClassA* obj_ : vecA) {
    Assert(dynamic_cast<ClassB*>(obj_)); // debug build sanity check
    auto* obj = static_cast<ClassB*>(obj_);
    obj->DoSomething();
  }
}

答案 1 :(得分:2)

容器包装器怎么样?我们先来看一下用法:

void iterate()
{
    for (ClassB* obj : cast_range<ClassB*>(vecA))
    {
        obj->DoSomething();
    }
}

这是一个可能的实现:

template<typename Target, typename Underlying>
struct cast_iterator_t
{
    Underlying it;

    Target operator*() const
    {
        return (Target) *it;
    }

    bool operator==(cast_iterator_t that) const
    {
        return it == that.it;
    }   

    bool operator!=(cast_iterator_t that) const
    {
        return it != that.it;
    }   

    cast_iterator_t& operator++()
    {
        ++it;
        return *this;
    }

    cast_iterator_t operator++(int)
    {
        cast_iterator_t old(*this);
        ++*this;
        return old;
    }
};

template<typename Target, typename Underlying>
cast_iterator_t<Target, Underlying> cast_iterator(Underlying it)
{
    return {it};
}

template<typename Target, typename Range>
struct cast_range_t
{
    Range& range;

    decltype(cast_iterator<Target>(std::begin(range))) begin()
    {
      return cast_iterator<Target>(std::begin(range));
    }

    decltype(cast_iterator<Target>(std::end(range))) end()
    {
      return cast_iterator<Target>(std::end(range));
    }
};

template<typename Target, typename Range>
cast_range_t<Target, Range> cast_range(Range& range)
{
    return {range};
}