我有一堆类似集合的COM接口,我正在尝试编写类似STL的迭代器.我有迭代器工作和专门的begin()和end()来返回我的迭代器.一切都很完美!除了,当我尝试使用begin(std :: vector)时,它使用了我对begin()的一般特化.由于这些COM对象不是从基本集合对象扩展,我首先尝试:
template< class CollType > CollectionIterator<CollType> begin( CollType coll )
我明白为什么重载决议没有为std :: vector选择正确的begin(),但我不知道如何解决这个问题.
不幸的是,我没有一个基本集合类来专门化coll参数.我假设我需要像SFINAE这样的东西,只有在合适的成员存在的情况下才能解决这些专业化问题.我试过了:
template< class CollType,typename std::enable_if< std::is_member_pointer< decltype(&CollType::GetItem) >::value >::type > CollectionIterator<CollType> begin( CollType coll )
(其中GetItem是CollType的方法)
除了一些变化,无济于事.更糟糕的是,这些集合是COM智能指针,所以我不确定GetItem是否会实际注册为智能指针的成员.
对正确方向的任何见解都会很棒,我一直都是围着这个方向跑.
解决方法
如果你总是使用一些特定的COM智能指针来处理棘手的集合(例如_com_ptr_t< T>),你可以用这种方式定义begin()特化:
template<class T> your_iterator_type<T> begin(_com_ptr_t<T>& collection)
如果这是不可接受的,请尝试另一种可能的方式(仅当您使用Visual C并且不关心非标准时) – 使用Microsoft特定扩展 – __if_exists / __ if_not_exists语句:
template<class T> typename T::iterator begin_ex(T& collection) { __if_exists(T::GetItem) { return my_collection_begin(collection); // Use custom impl } __if_not_exists(T::GetItem) { return std::begin(collection); // Use standard impl } }