免责声明:对于迂腐类型(或迂腐,如果你想迂腐......),我通常将这里的“重载”一词称为“创建具有名称的函数begin
andend
和 do using std::begin; using std::end;
。” ,相信我,我写起来一点也不乏味,但很难读,而且读起来很多余。:p.
我基本上会给你这种技术的可能用例,然后是我的结论。
案例 1 - 您的begin
和end
方法与标准容器的行为不同
您可能需要重载std::begin
andstd::end
函数的一种情况是,当您以不同的方式使用您的类型的begin
andend
方法,而不是提供对对象元素的类似迭代器的访问,并且想要重载std::begin
andstd::end
调用用于迭代的开始和结束方法。
struct weird_container {
void begin() { std::cout << "Start annoying user." }
void end() { std::cout << "Stop annoying user." }
iterator iter_begin() { /* return begin iterator */ }
iterator iter_end() { /* return end iterator */ }
};
auto begin(weird_container& c) {
return c.iter_begin();
}
auto end(weird_container& c) {
return c.iter_end();
}
但是,您不会也不应该做这样疯狂的事情,因为如果与 的对象一起使用 range-for 会破坏weird_container
,根据 range-for 的规则,weird_container::begin()
andweird_container::end()
方法将在独立函数变体之前找到。
因此,这种情况带来了不使用您提出的内容的论点,因为它会破坏该语言的一个非常有用的特性。
案例 2 -begin
根本end
没有定义方法
另一种情况是您没有定义begin
andend
方法。这是一种更常见和适用的情况,当您希望在不修改类接口的情况下将类型扩展为可迭代时。
struct good_ol_type {
...
some_container& get_data();
...
};
auto begin(good_ol_type& x) {
return x.get_data().begin();
}
auto end(good_ol_type& x) {
return x.get_data().end();
}
这将使您能够在good_ol_type
(算法、范围等)上使用一些漂亮的功能,而无需实际修改其界面!这符合 Herb Sutter 的建议,即通过非成员非好友函数来扩展类型的功能。
这是一个很好的案例,您实际上想要重载std:;begin
和std::end
.
结论
因为我从来没有见过有人像第一种情况那样做(除了我的例子),那么你真的想使用你提出的和超载的东西std::begin
以及std::end
适用的地方。
我没有在这里包括你定义了begin
和end
方法的情况,以及begin
与方法end
做不同事情的函数。我相信这种情况是人为的、不正确的和/或由一个没有太多经验深入调试器或阅读新模板错误的程序员完成的。