uk4*_*321 7 c++ argument-dependent-lookup
我想使用基于范围for来迭代UTF8编码的unicode代码点std::string.我定义我自己begin,并end在全局命名空间,但begin和end在std命名空间中被优先(即那些由ADL找到).有什么方法可以选择我自己的功能吗?
例:
const char* begin(const std::string& s) {
std::cout << "BEGIN";
return s.data();
}
const char* end(const std::string& s) {
std::cout << "END";
return s.data() + s.length();
}
int main() {
std::string s = "asdf";
for (char c : s)
std::cout << c;
}
Run Code Online (Sandbox Code Playgroud)
我希望它打印BEGINENDasdf(或ENDBEGINasdf)但它打印asdf.
除了for使用合格的名称做手册之外别无他法吗?
包装std::string你自己的类型.通过使其成为模板,您可以自定义任何现有容器并向其添加自己的范围逻辑.它与你的第一次尝试甚至没有什么不同.
#include <string>
#include <iostream>
template <typename S>
struct custom_container {
S &s_;
custom_container (S &s) : s_(s) {}
auto begin() -> decltype(s_.begin()) {
std::cout << "BEGIN";
return s_.begin();
}
auto end() -> decltype(s_.end()) {
std::cout << "END";
return s_.end();
}
};
template <typename S>
custom_container make_container (S &s) {
return custom_container <S> (s);
}
int main () {
std::string t = "asdf";
auto s = make_container(t);
for (char c : s) {
std::cout << c;
}
}
Run Code Online (Sandbox Code Playgroud)
输出
BEGINENDasdf
小智 6
N3337 6.5.4/1:
(...)begin-expr和end-expr确定如下:
-如果
_RangeT是一个数组类型,开始-EXPR和最终EXPR是__range和__range + __bound分别(...);- 如果
_RangeT是类类型,则在类的范围内查找unquali fi ed-id sbegin,end就_RangeT好像通过类成员访问查找(3.4.5),以及是否(或两者)找到至少一个声明, begin-expr和end-expr分别是__range.begin()和__range.end();-否则,开始-EXPR和最终EXPR是
begin(__range)和end(__range)表示,其中begin和end被查找与参数相关的查找(3.4.2).出于此名称查找的目的,namespacestd是关联的命名空间.
换句话说,它将调用std::string's' begin和end成员函数(第二个列表项目符号).正确的解决方案是提供一个包装类,如安东尼的答案所示.
注意:如果使用-std=c++1y,可以省略尾随的decltype.
您还可以编写一个typedef来减少输入:
typedef custom_string<std::string> cs;
for (char c : cs(t)) {
std::cout << c;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
226 次 |
| 最近记录: |