C++11的for设计有个小缺陷,对range的begin和end要求为相同的类型。
例如:std::vector<int> vec; vec.begin() 和 vec.end()是相同类型的。
例如:{1,2,3,4,5,6} 被编译器生成std::initialize_list<int>容器,也具有相同类型的begin()和end() 注:迭代器类型可简单的理解为int*
因此:for ( int i : {1,2,3,4,5,6} )
do_someting();
被编译器展开的伪代码为:
1 { 2 auto&& __range = {1,2,3,4,5,6} ; 3 for (auto __begin = __range.begin() , __end = __range.end(); 4 __begin != __end; ++__begin) 5 { 6 i = *__begin; 7 do_something(); 8 } 9 }
我们知道,int a=1, b=1.0f ; b的类型也是int, 而不是double
同理 auto a=1, b=1.0; 也具有相同的行为,b的类型同第一个变量a的类型。
C++11对for的处理,略显不足。因为只要求__end与__begin能比较不同即可,而不需要强制为相同的类型。
C++17 对for做了改进。
{ auto && __range = range_expression ; auto __begin = begin_expr ; auto __end = end_expr ; for ( ; __begin != __end; ++__begin) { range_declaration = *__begin; loop_statement } }
例子:
#include <iostream> #include <string> // a struct to get the first word of a string struct FirstWord { std::string data; // declare a predicate to make ' ' a string ender struct EndOfString { bool operator()(std::string::iterator it) { return (*it) != '\0' && (*it) != ' '; } }; std::string::iterator begin() { return data.begin(); } EndOfString end() { return EndOfString(); } }; // declare the comparison operator bool operator!=(std::string::iterator it, FirstWord::EndOfString p) { return p(it); } // test int main() { for (auto c : {"Hello World !!!"}) std::cout << c; std::cout << std::endl; // print "Hello World !!!" for (auto c : FirstWord{"Hello World !!!"}) // works with gcc with C++17 enabled std::cout << c; std::cout << std::endl; // print "Hello" }