从对象创建矢量包装器,该对象只允许使用索引访问向量

Creation of a vector wrapper from an object which only allows accessing vector with index

本文关键字:对象 许使用 访问 向量 索引 创建 包装      更新时间:2023-10-16

我创建了一个用于使用可链过滤器和映射操作的类,主要用于避免循环冗余。

例如

std::vector<ObjectASharedPtr> temp = GetListOfA();
FunctionalIteratableWrapper<ObjectASharedPtr> wrapper( temp );
wrapper.Filter([]( ObjectASharedPtr objA ){ return objA->isApple(); } ).Map([]( ObjectASharedPtr objA ){ return objA->Bite(); })

我的班级的简短版本可以在问题的底部看到,以免用长长的代码破坏问题。

当我将矢量作为" std :: vector"获得时,它的功能非常完美。我可以轻松地启动包装纸。

,但是现在有一个旧代码,它不会直接将数据作为列表,而是使用索引:

auto count = LegacyObjList->getCount(); 
for ( int i = 0; i < count; i++ )
    LegacyObj.getObjByIndex(i);

当前我想用这种结构实例化我的functionalatableWrapper,该结构只允许使用索引访问我需要执行:

std::vector<LegacyObj> tempVec;
auto count = LegacyObjList->getCount(); 
for ( int i = 0; i < count; i++ )
    tempVec.push_back(LegacyObj.getObjByIndex(i));
FunctionalIteratableWrapper<LegacyObj> wrapper(temp);

我想避免使用此循环,我现在每次都使用此对象创建包装器,该对象只允许使用索引访问。最好的解决方案应该是什么?

template< typename Value >
class FunctionalIteratableWrapper
{
public:

    /*!
     * brief A copy ctor like ctor. Which initiates this struct directly from vector of Iteratable.
     * param list vector of Iteratable
     */
    FunctionalIteratableWrapper( const std::vector<Value>& list  )
    {
        iteratableList = list;
    }
    /*!
     * brief Default ctor
     */
    FunctionalIteratableWrapper()
    {
    }
    template <typename F>
    FunctionalIteratableWrapper& Filter( F filterFunction, bool isReturnOneElement = false )
    {
        std::vector<Value> newList;
        for ( size_t i = 0; i < iteratableList.size(); i++)
        {
            if ( filterFunction(iteratableList[i]) )
            {
                newList.push_back(iteratableList[i]);
                if ( isReturnOneElement )
                   break;
            }
        }
        iteratableList = newList;
        return *this;
    }
,
    template < typename T, typename F >
    T Find( F filterFunction)
    {
        for ( size_t i = 0; i < iteratableList.size(); i++)
        {
            if ( filterFunction(iteratableList[i]) )
                return Cast<typename T::element_type>(iteratableList[i]);
        }
        return T();
    }
    template <typename T, typename F>
    FunctionalIteratableWrapper& Map( F applyFunction)
    {
        for ( size_t i = 0; i < iteratableList.size(); i++)
        {
            auto castedTerrain = Cast<typename T::element_type>(iteratableList[i]);
            if ( castedTerrain )
                applyFunction(castedTerrain);
        }
        return *this;
    }
    void Append( Value newElement )
    {
        iteratableList.push_back( newElement );
    }

    std::vector<Value> iteratableList;
};

处理此操作的简单方法是编写ADL辅助功能。

首先更改构造函数:

FunctionalIteratableWrapper( std::vector<Value> list  ):
  iterableList(std::move(list))
{
}

我们现在支持便宜的搬入。

接下来,创建一个名称空间:

namespace my_utility {
  namespace helper1 {
    template<class T, class A>
    std::vector<T, A> to_vector( std::vector<T, A> in ) {
      return std::move(in);
    }
  }
  namespace helper2 {
    using ::my_utility::helper1::to_vector;
    template<class T>
    auto as_vector( T&& t )
    -> decltype( to_vector( std::forward<T>(t) ) )
    {
      return to_vector( std::forward<T>(t) );
    }
  }
  using ::my_utility::helper2::as_vector;
}

现在调用::my_utility::as_vector(x)to_vector(x)上进行ADL查找。如果找不到它,它试图将x推断为std::vector<T,A>并返回副本。

现在我们添加了一个构造函数:

template<class T,
  class=std::enable_if_t< !std::is_same< std::decay_t<T>, FunctionalIteratableWrapper >::value >
>
FunctionalIteratableWrapper( T&& t ):
  iterableList(::my_utility::as_vector(std::forward<T>(t))
{
}

我们几乎在那里!

LegacyObj的命名空间中,写下:

std::vector<LegacyObj> to_vector( LegacyObjList const* pList ) {
  if (!pList _obj) return {};
  std::vector<LegacyObj> retval;
  int size = pList->getCount();
  retval.reserve(size);
  for (int i = 0; i < size; ++i)
    retval.push_back(pList->getObjByIndex(i);
  return retval;
}

,它将由as_vector神奇地找到(嗯,使用ADL)。

现在可以将LegacyObjList const*隐式转换为您的FunctionalInterableWrapper

未测试的代码。您可以首先编写to_vector,然后手动测试并获得99%的方式。

然后执行::my_utility::as_vector技巧。

最后,查看您是否可以获取调用as_vector工作的构造函数。

每个添加值,并且可以与其他值分开写。