如何获得"可分配类型"对于C ++中的任意(STL)输出迭代器

时间:2015-03-09 17:03:44

标签: c++ templates iterator

对于类型为value_type的输出迭代器,C ++标准要求std::iterator_traits<OutputIterator>中的typedef void设置为OutputIterator。尽管如此,对于给定的输出迭代器类型OutputIterator来说,推断它是完全合理的(并且在我的代码中是绝对必需的),可接受的类型(不引用任何隐式转换)o形式的表达

*it = o

其中itOutputIterator类型的对象。

理想情况下,我想使用TMP定义一个定义typedef my_iterator_traits的模板类assignable_type,以便my_iterator_traits<OutputIterator>::assignable_type等于decltype( o )。有什么建议如何实现这个?

如果我通过定义模板特化来枚举所有可能的STL迭代器类型,我甚至不知道如何实现这一点。例如,以下代码不会编译,因为编译器无法推导出模板参数T

template <typename Iterator> struct my_iterator_traits;

//[...]

//Does NOT compile, compiler cannot deduce type T
template <typename T> struct my_iterator_traits<std::vector<T>::iterator>
{
    typedef typename std::vector<T>::value_type assignable_type;
    //Another option, but I think not so clean:
    //typedef T assignable_type;
};

编辑:对于我遇到问题的情况,这是一个草图(没有上下文)。建议您要在二进制级别编辑容器的元素。对象first是一个(输入)迭代器,它允许我访问已知大小的输入元素(在这种情况下为2个字节)。我想把它们写成&#34;二进制输出&#34;通过输出迭代器result接受单字节(输出)对象。即,我不想指定&#34;单字节类型&#34;输出迭代器应该是。 (准)代码:

const typename my_iterator_traits<OutputIterator>::assignable_type* ptr;

for( size_type i = 0; i < n; ++i, ++first )
{
    ptr = reinterpret_cast<const typename my_iterator_traits<OutputIterator>::assignable_type*>( &( *first ) );
    *result = ptr[0]; ++result;
    *result = ptr[1]; ++result;
}

我担心如果没有reinterpret_cast,可能会发生一些隐式转换改变二进制结构的情况。我只想将这些位复制到目标,无论目标是什么以及如何通过输出迭代器提供的抽象接口来访问它。唯一的要求是可以通过输出迭代器逐字节访问目标。

1 个答案:

答案 0 :(得分:2)

您的问题一般无法解答。

作为一个例子,这里是一个输出迭代器,虽然它在技术上只需要一种类型operator=,但它实际上采用任何类型:

template<class OS>
struct ostream_proxy {
  void* v;
  void(*f)(void*, OS&);
  template<class O>
  friend O& operator<<(O& o, ostream_proxy p) {
    p.f(p.v, o);
    return o;
  }
  template<class X, class pX = typename std::decay_t<X>::type*>
  ostream_proxy( X&& x ):
    v(&x),
    f(
      [](void* px, OS& os) {
        os << &static_cast<pX>(px);
      }
    )
  {}
};
template<class OS>
std::ostream_iterator<ostream_proxy<OS>> it_out(OS& os) {
  return {os};
}
template<class OS, class CharT>
std::ostream_iterator<ostream_proxy<OS>> it_out(OS& os, const CharT* delim) {
  return {os, delim};
}

现在上面我很懒,我使用std::ostream_iterator代理类型。但是,输出迭代器上的operator=是重载的,或者是template运算符。如果是这种情况,则没有&#34;一种没有转换的类型&#34;输出迭代器接受的。

(一个不太懒惰/ hacky的版本会重新实现ostream_iterator<>以获得template operator=,只需编写任何类型。在我看来,这将是一个很好的实现std::ostream_iterator<void>std::less<void>(又名std::less<>))。

很容易检查是否有办法将给定类型分配给迭代器,但确定哪种类型涉及&#34;没有转换&#34;在一般情况下是不可能的。在特定情况下,有无数的黑客攻击。

与大多数&#34;给定一个功能对象,给我签名&#34;这个问题假定一个固定类型,或者应该是一个固定类型。输出迭代器具有可用于加载它们的有效表达式,而不是特定类型。