// 自家製タグ. pointer, std::vector, std::arrayなどを想定
namespace detail {
struct contigous_storage_iterator_tag : pubic std::random_access_iterator_tag;
};
//// メンバ関数
template <class InputIterator>
void Buffer::insert(const_iterator where, InputIterator first, InputIterator last)
{
_insert(where, first, last, GetIterCategory(first));
}
void Buffer::_insert(const_iterator where, InputIterator first, InputIterator last, std::forward_iterator_tag)
{
// list, deque, ... 等のイテレータ用の処理
}
void Buffer::_insert(const_iterator where, InputIterator first, InputIterator last, detail::contigous_storage_iterator_tag)
{
// pointer, vector, array,... 等のイテレータ用の処理
}
// 自家製タグを返すtraits風のものを作ろうとしたがうまくいかない
template <class Iter, bool isContigous=false> struct IteratorCategory {
typedef typename iterator_traits<Iter>::iterator_category type;
};
// 推論できない
template <class T, class A, class Iter>
struct IteratorCategory<Iter, std::is_same<Iter, typename vector<T,A>::iterator>::value> {
typedef ato::gl::detail::DeviceVector::contigous_storage_iterator_tag type;
};
ちなみに、現在は以下のように動的に対処しています。
template <class InputIterator> // For randam_access_iterator_tag
void Buffer::insert(const_iterator where, InputIterator first, InputIterator last)
{
ptrdiff_t count = std::distance(first, last);
if( count != 0 )
{
if( &*(last-1) - &*first == count - 1 ) // アドレスの差とイテレータの差が同じ. (*lastにはアクセスできない)
_insert(where, first, last, std::forward_iterator_tag());
else
_insert(where, first, last, detail::contigous_storage_iterator_tag());
}
}