C++ 如何实现我的自定义范围for循环?

C++ 如何实现我的自定义范围for循环?,c++,c++11,ranged-loops,C++,C++11,Ranged Loops,我非常喜欢C++11及更高版本支持的基于范围的for循环。我想用一些理解的理由来模拟它。以下是一个例子: // 1 //#define ranged_for(X, T) \ // for (std::vector<int>::iterator beg{ T.begin() },\ // end{ T.end() }; beg != end; X = *beg, ++beg)\ // 2 //#define ranged_for(X, T) \ // for (std:

我非常喜欢C++11及更高版本支持的基于范围的for循环。我想用一些理解的理由来模拟它。以下是一个例子:

// 1
//#define ranged_for(X, T) \
//  for (std::vector<int>::iterator beg{ T.begin() },\
//      end{ T.end() }; beg != end; X = *beg, ++beg)\

// 2
//#define ranged_for(X, T) \
//  for (std::vector<int>::iterator beg{ T.begin() },\
//      end{ T.end() }; beg != end; ++beg, X = *beg)\

// 3
#define ranged_for(X, T) \
    for (std::vector<int>::iterator beg{ T.begin() },\
        end{ T.end() }; beg != end; ++beg)\
            X = *beg, 



int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    auto i{ 0 };
    ranged_for(i, data)
        std::cout << i << std::endl;

    std::cout << std::endl;
    std::cin.get();
    return 0;
}

这是因为上面的一行被视为一条语句。有没有更好的方法和解释。谢谢你们所有的好伙计们
int i;
ranged_for(i, data)
    // ...
vs

到目前为止,您需要预先退出
i
。您不能以这种方式使用引用!现在让我们想象一下,我们设法使它变得更聪明:

ranged_for(int& i, data)
vs

你得到了什么?用逗号代替冒号???老实说,这不值得努力。一个更值得考虑的场景:

auto i = data.end();
for(auto j = data.begin(); j != data.end(); ++j)
{
    if(someCondition)
        i = j;
}
if(i != data.end())
{
    // ...
}

好吧,这已经相当罕见了。在许多情况下,如果不是大多数情况,您可以将if的外部主体移动到内部主体中,并在末尾添加一条
break
指令。在这几种情况下,你仍然不能这么做——那么,我将使用显式迭代器循环——写的不是那么重…

为什么你反对C++基于循环的那么多?

int i;
ranged_for(i, data)
    // ...
vs

到目前为止,您需要预先退出
i
。您不能以这种方式使用引用!现在让我们想象一下,我们设法使它变得更聪明:

ranged_for(int& i, data)
vs

你得到了什么?用逗号代替冒号???老实说,这不值得努力。一个更值得考虑的场景:

auto i = data.end();
for(auto j = data.begin(); j != data.end(); ++j)
{
    if(someCondition)
        i = j;
}
if(i != data.end())
{
    // ...
}

好吧,这已经相当罕见了。在许多情况下,如果不是大多数情况,您可以将if的外部主体移动到内部主体中,并在末尾添加一条
break
指令。在这几种情况下,您仍然无法做到这一点—好吧,那么我将使用显式迭代器循环—编写它没有那么繁重…

这应该适用于单行和多行范围:

#define ranged_for(X, T) \
    for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it)
或者可以用来自动推断类型
X
的版本应该是,但它需要一个额外的宏:

#define ranged_for(X, T) \
    {decltype(T)::value_type X; for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it) {

#define range_end }}

int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    ranged_for(i, data)
        std::cout << i << std::endl;
    range_end
}
#定义(X,T)的范围\
{decltype(T)::value_type X;for(auto-it=std::begin(T);it!=std::end(T)&&(X=*it,true);+it){
#定义范围_end}
int main(){
向量数据{7543565792123};
(i,数据)的范围单位

std::cout这应该适用于单行和多行范围:

#define ranged_for(X, T) \
    for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it)
或者可以用来自动推断类型
X
的版本应该是,但它需要一个额外的宏:

#define ranged_for(X, T) \
    {decltype(T)::value_type X; for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it) {

#define range_end }}

int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    ranged_for(i, data)
        std::cout << i << std::endl;
    range_end
}
#定义(X,T)的范围\
{decltype(T)::value_type X;for(auto-it=std::begin(T);it!=std::end(T)&&(X=*it,true);+it){
#定义范围_end}
int main(){
向量数据{7543565792123};
(i,数据)的范围单位


std::你能在条件语句中隐藏赋值吗?la:
beg!=end&&(X=*beg,true);
为什么要使用宏?
for(auto const&i:data)
几乎是相同的长度,并且做你想做的事。快速好奇:
auto i{0}背后的逻辑是什么
?我可以理解使用auto来减少输入长而难看的迭代器,但是这里的
int
将更少的字符!这只是一般的懒惰吗?还是你来自javascript这样的语言,在那里你可以
var
任何东西?可以很容易地替换。如果你ant/需要在循环体中有多个表达式…您可以将赋值隐藏在条件语句a la:
beg!=end&&(X=*beg,true);
为什么要使用宏?
for(auto const&i:data)
的长度几乎相同,并且可以执行您想要的操作。快速好奇:
auto i{0}
?我可以理解使用auto来减少输入长而难看的迭代器,但是这里的
int
将更少的字符!这只是一般的懒惰吗?还是你来自javascript这样的语言,在那里你可以
var
任何东西?可以很容易地替换。如果你ant/需要在循环体中有多个表达式…但需要在循环外部预先声明
X
,这是不必要的(至少在大多数情况下)扩展它的范围。引用也不能这样使用。当然,但这似乎不是OP的问题。范围大于要求是不好的风格。我们不应该鼓励这样做…当然。我不是有意鼓励这样做。我只是尝试用一些更好的方法来回答,因为OP要求这样做。我添加了一个用于自动推断的版本类型也一样。:-)OP只是试图用定义来模拟它。我不认为它是用来取代真实的东西。它可能看起来很难看,但旨在帮助OP完成问题所在。但是需要预先退出循环之外的
X
,这是不必要的(至少在大多数情况下)扩展它的范围。引用也不能这样使用。当然,但这似乎不是OP的问题。范围大于要求是不好的风格。我们不应该鼓励这样做…当然。我不是有意鼓励这样做。我只是尝试用一些更好的方法来回答,因为OP要求这样做。我添加了一个用于自动推断的版本类型也一样。:-)OP只是试图用定义来模拟它。我不认为它是用来取代真实的东西。它可能看起来很难看,但旨在帮助OP完成问题所在。我认为OPs的重点是编写适用于旧版本(C++11之前)的类似代码编译器。
匿名变量宏是在C++11
中引入的,
扩展初始值设定项列表仅在-std=C++11
中可用,并且在C++11之前的代码中,g++和clang++都存在一些次要问题。@TEDLYGMO(@#*%!)-你是对的…早在C++11之前,GCC就支持可变宏了,据我所知,甚至MSVC也支持可变宏。可以用命名参数代码代替它,但这会阻止使用任何逗号(无论出于何种目的)。更严重的问题是,未命名(好吧,可能会添加名称),尤其是本地类(这种方法致命)也不支持as模板参数。Initia