考虑:
#include <iostream>
#include <vector>
class A
{
public:
typedef bool TAll;
static TAll All;
typedef std::vector<int> TVec;
static TVec m_sVec;
static TVec::iterator begin() { return m_sVec.begin(); }
static TVec::iterator end() { return m_sVec.end(); }
};
A::TVec A::m_sVec;
A::TAll A::All;
A::TVec::iterator begin(A::TAll& all) { return A::begin(); }
A::TVec::iterator end(A::TAll& all) { return A::end(); }
int _tmain(int argc, _TCHAR* argv[])
{
A::m_sVec.push_back(1);
A::m_sVec.push_back(2);
A::m_sVec.push_back(3);
for (auto a : A::All) {
//for (auto a = begin(A::All); a != end(A::All); a++) {
std::cout << a << std::endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
具有基于for循环的范围的版本(因此此代码原样)在MSVC2013中给出了以下错误:
1><snip>: error C3312: no callable 'begin' function found for type 'A::TAll'
1><snip>: error C3312: no callable 'end' function found for type 'A::TAll'
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会(4.8.3)说(最后两行):
/usr/include/c++/4.8.3/initializer_list:99:5: note: template<class _Tp> constexpr cons
t _Tp* std::end(std::initializer_list<_Tp>)
end(initializer_list<_Tp> __ils) noexcept
^
/usr/include/c++/4.8.3/initializer_list:99:5: note: template argument deduction/subs
titution failed:
main.cpp:31:18: note: mismatched types 'std::initializer_list<_Tp>' and 'bool'
for (int a : A::All) {
Run Code Online (Sandbox Code Playgroud)
使用函数(被注释掉的函数)的'normal'循环工作(当然,在循环内取消引用'a'之后); 我对标准和Stroustroup的理解是它们应该是等价的.但我猜不是.那么这里的问题是什么?谢谢.
每个C++ 11 [stmt.ranged]/1,你的循环:
for (auto a : A::All) {
std::cout << a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
相当于:
{
auto && __range = (A::All);
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
auto a = *__begin;
{
std::cout << a << std::endl;
}
}
}
Run Code Online (Sandbox Code Playgroud)
其中表达的确定begin-expr和end-expr取决于类型_RangeT初始化表达的A::All(bool在这种情况下):
- 如果
_RangeT是数组类型,...- 如果
_RangeT是类类型,...- 否则,开始-EXPR和最终EXPR是
begin(__range)和end(__range)表示,其中begin和end被查找与参数相关的查找(3.4.2) [ 重点加入.出于此名称查找的目的,namespacestd是关联的命名空间.
由于bool既不是数组类型也不是类类型,所以第三个子弹适用; 该表达式begin(__range)和end(__range),但begin和end使用ADL与被解析std为关联的命名空间.每3.4.2 [basic.lookup.argdep]/2:
对于
T函数调用中的每个参数类型,都有一组零个或多个关联的命名空间以及一组零个或多个要考虑的关联类.命名空间和类的集合完全由函数参数的类型(以及任何模板模板参数的命名空间)决定.用于指定类型的Typedef名称和using-declarations对此集合没有贡献.[ 强调添加 ]命名空间和类的集合按以下方式确定:
- 如果T是基本类型,则其关联的命名空间和类集都是空的.
- ...
所以begin,end只在std命名空间中查找,其中找到了几个声明,但没有一个可以接受类型的参数bool.该计划格式不正确.