ADL和容器功能(开始,结束等)
ADL and container functions (begin, end, etc)
c 11及以后定义命名空间std中的自由功能begin
,end
,empty
等。对于大多数容器,这些功能调用相应的成员函数。但是对于某些容器(例如valarray
),这些免费功能被超载(initializer_list没有成员begin())。因此,应使用任何容器免费功能,并从std
ADL以外的其他命名空间找到容器的功能:
template<typename C>
void foo(C c)
{
using std::begin;
using std::end;
using std::empty;
if (empty(c)) throw empty_container();
for (auto i = begin(c); i != end(c); ++i) { /* do something */ }
}
问题1 :我对吗?begin
和end
是否可以通过ADL找到?
但ADL规则指定,如果参数的类型是类模板专业化ADL,则包括所有模板参数的名称空间。然后boost.range库发挥作用,定义boost::begin
,boost::end
等。这些功能是这样定义的:
template< class T >
inline BOOST_DEDUCED_TYPENAME range_iterator<T>::type begin( T& r )
{
return range_begin( r );
}
如果我使用 std::vector<boost::any>
和boost.range,我会遇到麻烦。STD :: BEGIN和BOOST :: BEGIN OVERLOADS是模棱两可的。这样,我无法编写可以通过ADL找到免费begin
的模板代码。如果我明确使用std::begin
,我希望任何非std::
容器都有成员begin
。
问题2 :在这种情况下我该怎么办?
依赖成员函数的存在?最简单的方式。
ban bost.range?好吧,采用容器而不是一对迭代器的算法是令人信服的。Boost.Range适配器(懒洋洋地将算法应用于容器的容器)也令人信服。但是,如果我不使用boost.range在我的代码中,则仍然可以在boost库中使用(范围除外)。这使模板代码真的很脆弱。
ban Boost?
几年前,我遇到了一个类似的问题,我的代码突然开始获得std::begin
和boost::begin
之间的歧义。我发现这是由于使用boost。操作员来帮助定义课程,即使它甚至不是公共基类,也不是所涉及类型的用户。在嵌套的某个地方,某个地方的随机更改导致#include <boost/range/begin.hpp>
包含文件,从而使boost::begin
可见编译器。
我向邮件列表抱怨直接在增强名称空间中放置类,而不是在嵌套的类中,并通过using
声明将其暴露;直接在Boost名称空间中定义的所有内容都可以通过意外ADL互相踩踏。
我今天只是试图重现这个,现在似乎有弹性的反对这种歧义!查看定义,boost::begin
本身在一个内部名称空间中,因此,如果您没有在自己的范围内提供自己的using boost::begin;
,则可以通过不合格的查找找到它。
我不知道此修复程序是多久以前的。(如果您仍然可以复制它,请发布一个完整的程序和平台详细信息。)
所以您的答案是:
为了提升,请不再担心(如有必要,请提升)。
对于新代码,切勿在与其任何定义类型相同的名称空间中定义名为begin
的免费功能。
- 根据用户输入用字母填充矢量,并将"开始"和"结束"放在四肢
- 如何在 c++ 中确定一条指令(以字节为单位)在哪里结束,另一条指令从哪里开始?
- 如何显示函数开始、结束行和函数体?
- C++ 从具有开始位置和结束位置的列表中删除
- C++程序从主程序开始执行并在主程序结束?
- 如何使用Chrono或ctime libaray输入设置的开始和结束时间
- 如何使用 AWS C++ 开发工具包在给定的开始和结束日期范围内列出 S3 中的文件
- 编写一个函数,在开始和结束处添加括号,使所有括号匹配并返回
- 如何通过指定开始值、结束值和步骤来生成值序列
- 如何获取由 new 创建的数组的开始和结束
- 是否可以在基于范围的 for 循环中使用模板化的开始/结束方法
- 重写自定义数组类的运算符/开始/结束
- f流删除特定的开始到结束行
- 取代表开始/结束的数字对,并删除重叠
- 如何将迭代器(包括结束和开始之前的迭代器)测试到列表或forward_list保持有效
- 设置从文件中读取的开始和结束限制
- 为什么 std::variant 使用开始和结束迭代器进行编译?
- 如何为一个类提供多个开始/结束代理
- 如何有效地从C++集中删除开始和结束元素
- 加权图的开始和结束的最短路径