C++ 我可以创建一个没有底层容器对象的空范围(迭代器对)吗?

C++ 我可以创建一个没有底层容器对象的空范围(迭代器对)吗?,c++,c++11,boost,C++,C++11,Boost,我有一个类似于以下的课程: struct Config { using BindingContainer = std::map<ID, std::vector<Binding>>; using BindingIterator = BindingContainer::mapped_type::const_iterator; boost::iterator_range<BindingIterator> bindings(ID id) cons

我有一个类似于以下的课程:

struct Config
{
   using BindingContainer = std::map<ID, std::vector<Binding>>;
   using BindingIterator  = BindingContainer::mapped_type::const_iterator;

   boost::iterator_range<BindingIterator> bindings(ID id) const;
private:
   BindingContainer m_bindings;
};
struct-Config
{
使用BindingContainer=std::map;
使用BindingIterator=BindingContainer::mapped_type::const_迭代器;
迭代器范围绑定(ID)常量;
私人:
绑定容器m_绑定;
};
由于传递给
bindings()
ID
可能不存在,因此我需要能够在返回类型域中表示“no bindings”值

我不需要区分未知的
ID
和映射到空
向量的
ID
,因此我希望能够通过上面的接口实现这一点,并使用默认构造的迭代器返回空范围。不幸的是,尽管一个
ForwardIterator
DefaultConstructible
[C++11 24.2.5/1],但是比较单个迭代器的结果是未定义的[24.2.1/5],因此如果没有容器,这似乎是不可能的

我可以更改接口,例如将
迭代器范围
包装在
boost::optional
中,或者返回向量值;但是,前者对调用方来说有点笨重,而后者有不希望的复制开销

另一种选择是保持静态分配的空向量并返回其迭代器。在这种情况下,开销不会有问题,但如果可以的话,我想避免它

调整
映射
迭代器以生成可比较的默认构造迭代器是一种可能性,尽管似乎过于复杂

这里是否有其他选项支持在没有底层容器时返回空范围

(顺便说一句,我确信不久前我读过一篇关于在没有容器对象的情况下为标准容器类型生成空范围的工作论文或文章,但现在找不到任何内容。)


(注意我仅限于C++11特性,不过如果有其他方法需要更高的特性,我会感兴趣。)

不,没有。你的选择和你建议的一样。就个人而言,我可能会赞同从静态空向量劫持迭代器对的想法;我无法想象除了进程映像中的几个额外字节之外,这里会涉及到什么概念上的“开销”


这在C++14或C++17中都没有改变(到目前为止)。

您可以使用默认构造的
boost::iterator\u范围

from():

但是,如果创建默认构造的迭代器_范围,则 仍然可以调用其所有成员函数。该设计决策避免了 迭代器_范围对以下迭代器的范围施加限制: 它们不是单数的

示例如下:

在我看来,一个空范围应该是
开始
等于
结束
。。在C++14中,值初始化的前向迭代器可以相互比较,并且必须相等。@Joachim-是的,这是我想要的,但是AFAICT没有容器,我无法创建它,因为标准中引用了未定义的结果。@JonathanPotter-这在功能上等同于
boost::optional
,但是由于增加了性能损失和不太准确的语义。@sp2danny在大多数现代实现中,
std::vector::iterator
不是一个
T*
。默认构造的
boost::iterator\u范围有什么问题吗?
参考:但是,“任何奇点限制都是从底层迭代器类型传播的”,请注意您引用的最后一句话,“非奇点迭代器”“。按照我的理解,这意味着如果范围是单数,那么它不会施加任何约束,但是如果基础迭代器是单数的,那么您仍然必须遵守这些约束。不过我不太明白,因为这会使这一段毫无意义。也许默认构造的范围只是完全“绕过”封装的迭代器?从邮件列表中得到一些澄清可能很好。但是这是有希望的!让我们知道它是如何工作的我倾向于同意@LightnessRacesinOrbit对那里的文档的解释,所以我认为这是不可行的,但无论如何,谢谢。它工作得很好。虽然文档有点模糊,但它只是讨论了如果默认构造迭代器,与默认构造的
boost::range
相比会发生什么,以及底层迭代器只是传播的事实。这里的例子