2013-03-20 268 views
11

新的基于范围的for循环确实提高了可读性,并且非常易于使用。然而,考虑以下因素:C++ 11基于范围的for和map:可读性

map<Foo,Bar> FooAndAssociatedBars; 

for (auto& FooAndAssociatedBar : FooAndAssociatedBars) { 
    FooAndAssociatedBar.first.doSth(); 
    FooAndAssociatedBar.second.doSomeOtherThing(); 
} 

它可能是一个细节,但我觉得它会是更具可读性,如果我可以做类似:

for ((auto& foo, auto& bar) : FooAndAssociatedBars) { 
    foo.doSth(); 
    bar.doSomeOtherThing(); 
} 

你知道等效语法?

编辑: 好消息:C++ 17具有这不会忽略问题的提案,称为结构化绑定(见1)。在C++ 17,你应该能够写:

tuple<T1,T2,T3> f(/*...*/) { 
    /*...*/ 
    return {a,b,c}; 
} 
auto [x,y,z] = f(); // x has type T1, y has type T2, z has type T3 

解决了这个问题,可读性

+0

编译器会如何猜测'Foo'和'Bar'是指什么? – 2013-03-20 14:50:20

+0

@PeteBecker嗯,foo只是一个方便的方式来说“名字foo std :: pair的左边部分”。绝对而言,可以在编译时做到这一点:这只是一个符号方便。我想知道是否有可能通过重载或类似的方式获得这样的效果 – 2013-03-20 15:05:24

+0

是的,当然可以要求编译器知道'std :: pair'或查找任何具有名为'first'和'秒';这很专业,可能不适合标准化。下一个请求将是'元组'的所有元素... – 2013-03-20 15:15:45

回答

10

有没有这样的事情,只要你想。最接近的是申报循环内的变量:

for (auto& FooAndAssociatedBar : FooAndAssociatedBars) { 
    auto& foo = FooAndAssociatedBar.first; 
    auto& bar = FooAndAssociatedBar.second; 

    // ... 
} 
0

和当然,你总是要使用lambda表达式的可能性。

std::map<int, const char*> m { { 4, "hello" }, { 11, "c++" } }; 
convenient_for_each(m, [](int a, const char* b) { 
    std::cout << b << a << std::endl; 
    }); 
convenient_for_each(m, [](std::pair<int, const char> p) { 
    std::cout << p.first << p.second << std::endl; 
    }); 

或者包装成宏(不推荐)

FOREACH((int a, const char* b), m, std::cout << a << b << std::endl); 
FOREACH((std::pair<int, const char*> p), m, std::cout << p.first << p.second << std::endl); 

Hackish sample implementation at LWS

汽车将无法工作,虽然,我仍然在等待多态lambda表达式。我的方法在理论上也能够处理元组。

1

不是一个好主意。迟早,你会想要std::tuple相同,编译器应该能够自动使用tuple上的std::get<>。在我看来,你的方法现在只让你满意,而且你会发现这种方法存在问题(假设它是以这种方式实现的)。

标准委员会已经深入考虑设计了基于范围的循环。它比其他语言的foreach循环更好,并且它更短。将它与auto&结合起来,就完成了!

+1

“不是一个好主意,迟早你会想要一个std :: tuple,并且编译器应该能够自动地在元组上使用std :: get <>。那问题是? – Cubic 2013-03-20 17:12:54

+0

编译器的更多需求。 – Ajay 2013-03-20 17:36:01

+0

如何?我发现任何这样的语言特性将被定义为调用'std :: get'(很可能不合格的'get'),因此支持'std :: pair'和'std :: tuple'以及任何用户定义的'元组“像容器自动。 – Grizzly 2013-03-23 20:40:20