让我们假设我有以下Data
类:
struct Data {
char foo[8];
char bar;
};
下面的函数my_algorithm
,它接受一对char *
(类似于STL算法):
void my_algorithm(char *first, char *last);
对于Data
的foo
数据成员,而不是像这样调用my_algorithm()
:
Data data;
my_algorithm(data.foo, data.foo + 8);
我可以使用std::begin()
和std::end()
方便函数模板:
my_algorithm(std::begin(data.foo), std::end(data.foo));
我想要实现类似于Data
的bar
数据成员的东西。也就是说,不要写:
my_algorithm(&data.bar, &data.bar + 1);
我想写这样的东西:
my_algorithm(begin(data.bar), end(data.bar));
因此,我为本例定义了以下两个普通(非模板)函数:
char* begin(char& c) { return &c; }
char* end(char& c) { return &c + 1; }
这样我就可以编写如下代码:
Data data;
using std::begin;
using std::end;
my_algorithm(begin(data.foo), end(data.foo)); // ok - std::begin()/std::end()
my_algorithm(begin(data.bar), end(data.bar)); // Error!!!
使用上面的using
声明,我希望std::begin()
/std::end()
和::begin()
/::end()
分别处于相同的重载集中。由于函数::begin()
和::end()
是后一次调用的完美匹配,而且它们不是模板,所以我希望对my_algorithm()
的最后一次调用能够匹配它们。不过,我们根本不考虑一般的功能。结果编译失败,因为std::begin()
和std::end()
与调用不匹配。
从根本上说,后一种调用就像我写的那样:
my_algorithm(begin<>(data.bar), end<>(data.bar));
也就是说,重载解析过程只考虑函数模板(即std::begin()
/std::end()
),而不考虑普通函数(即::begin()
/::end()
)。
只有当我完全限定对::begin()
/::end()
的调用时,它才能正常工作
my_algorithm(::begin(data.bar), ::end(data.bar));
我在这里错过了什么?
发布于 2019-06-03 17:41:54
问题的标题是“重载std::begin()”。重载只有在同一范围内才有可能。也就是说,您不能重载来自不同范围的名称。在另一个范围内,我们只能努力帮助查找名称。本质上,这里的“使用std ::begin”声明隐藏了::begin的代码。有关参考,请参见S.Lippman:
作为两个不同名称空间的成员的函数不会相互重载。 使用声明的范围。在使用声明中引入的名称符合正常范围规则。在外部作用域中定义相同名称的实体将被隐藏。
一旦参数是char和char是基本类型,就不应该考虑参数依赖的查找--正如注释中提到的--没有与基本类型相关联的命名空间。同样,问题是:“我漏掉了什么?”--因此答案只集中在理由上--建议可能过于宽泛。
https://stackoverflow.com/questions/56432036
复制相似问题