我编写了这个C ++ 17代码,并期望它能够开箱即用。
class putc_iterator : public boost::iterator_facade<
putc_iterator,
void,
std::output_iterator_tag
>
{
friend class boost::iterator_core_access;
struct proxy {
void operator= (char ch) { putc(ch, stdout); }
};
auto dereference() const { return proxy{}; }
void increment() {}
bool equal(const putc_iterator&) const { return false; }
};
我试图通过将我的迭代器的成员typedef value_type
和reference
设置为void
来匹配所有标准OutputIterators的行为(因为这些类型是对于operator*
没有返回引用的迭代器没有意义。
In file included from prog.cc:2:
/opt/wandbox/boost-1.63.0/clang-head/include/boost/iterator/iterator_facade.hpp:333:50: error: cannot form a reference to 'void'
static result_type apply(Reference const & x)
^
看起来Boost正在尝试将生成的operator*
签名硬编码为reference operator*() const
。也就是说,boost::iterator_facade
可以通过简单地传递operator*()
返回的内容来推断dereference()
的正确返回类型;但出于某种原因,它只是没有玩耍。
解决方案是什么?我无法将proxy
作为基类的模板参数传递,因为proxy
尚未定义。 I could pull proxy
out into a detail namespace:
namespace detail {
struct proxy {
void operator= (char ch) { putc(ch, stdout); }
};
}
class putc_iterator : public boost::iterator_facade<
putc_iterator,
void,
std::output_iterator_tag,
detail::proxy
>
{
friend class boost::iterator_core_access;
auto dereference() const { return detail::proxy{}; }
void increment() {}
bool equal(const putc_iterator&) const { return false; }
};
但这看起来很尴尬,绝对是不应该的。&#34;
这是iterator_facade
中的错误吗?它是一个功能 - 不是一个错误?如果是后者,那么我假设如何使用它来创建OutputIterators?
另外,一个小小的挑剔:甚至我对细节命名空间的解决方法是&#34;错误&#34;从某种意义上来说,当我想要(与标准迭代器相同)时std::is_same_v<putc_iterator::reference, detail::proxy>
为std::is_same_v<putc_iterator::reference, void>
。
答案 0 :(得分:0)
Boost Iterator Facade当时表现不错,但现在它已经过时了,因为它不是很灵活(它与auto
不兼容,并且r值引用原则上可以通过解除引用来创建一个r值迭代器)。我不是立面概念,但它可以升级到C ++ 11。
此外,现在使用C ++ 11更容易从头开始编写迭代器。
无论如何,如果你需要定义reference
只是为了遵守要传递的参数,(如果你保证不使用它),你可以使用void*
而不是void
。 (或者也许为了一致性使用proxy&
并在类外定义它。)
class putc_iterator : public boost::iterator_facade<
putc_iterator,
void*,
std::output_iterator_tag
>
{
friend class boost::iterator_core_access;
struct proxy {
void operator= (char ch) { putc(ch, stdout); }
};
auto dereference() const { return proxy{}; }
void increment() {}
bool equal(const putc_iterator&) const { return false; }
};