8

Say, I want to iterate a number of pairs defined inline. Is there a shorter way to write:

for(auto pair : std::initializer_list<std::pair<int,int>>{{1,2}, {3,4}})
    // ...

?

IceFire
  • 4,016
  • 2
  • 31
  • 51

2 Answers2

14

Just specify the first element is a pair. The rest will be deduced automatically:

for(auto& pair : {std::pair<int,int>{1,2}, {3,4}})
  ;

The braced enclosed initializer is deduced to be std::initalizer_list, and the first element being named a pair will require all elements to be an initalizer for a pair.

You tagged C++11, but for completeness, it can be even shorter in C++17:

for(auto& pair : {std::pair{1,2}, {3,4}})
  ;

Due to class template argument deduction. If you don't have that, than std::make_pair will do if you want to maintain the benefits of template argument deduction:

for(auto& pair : {std::make_pair(1,2), {3,4}})
  ;

Though ostensibly, it isn't as useful for code golfing as the C++17 version.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • Nice one, thanks :) Based on your answer, I also found this version that works below C++17: `for(auto pair : {std::make_pair(1,2),{3,4},{5,6}})` – IceFire Sep 18 '17 at 14:22
  • @IceFire - Yeah, it works in C++11 too. The argument deduction can replace `make_pair` in C++17 however. – StoryTeller - Unslander Monica Sep 18 '17 at 14:23
  • 1
    Yes, I like this best. My compiler does not accept it so far, though. Anyways, we seem to have covered all options – IceFire Sep 18 '17 at 14:26
  • Would you want to capture the pairs by reference instead of value? On most platforms shouldn't two ints and a pointer both be 8-bytes, but the ints are one less layer of indirection? I guess I'd hope that both generate the same assembly after the optimizer ran... – RyanP Sep 18 '17 at 20:54
  • @RyanP - The initializer list content is immutable anyway, so if the OP intends to modify anything they'd need to operate on a copy either way. And if they don't, I feel your concerns are in the realm of premature optimization. – StoryTeller - Unslander Monica Sep 18 '17 at 20:58
2

The good ol' type alias:

using pairlist = std::initializer_list<std::pair<int,int>>;

for(auto pair : pairlist{{1,2}, {3,4}})
{
    // stuff happens here
}
Galik
  • 47,303
  • 4
  • 80
  • 117
  • this is actually longer – IceFire Sep 18 '17 at 14:23
  • @IceFire Not on average over more than one loop. – Galik Sep 18 '17 at 14:27
  • I have said nothing about multiple loops. In fact, wanting to put this list inline is a clear indicator that I have only one loop instance – IceFire Sep 18 '17 at 14:28
  • @IceFire Asking this question here, however, had created more typing than any possible shortening in the source. So bothering to ask this question is a clear indicator that there is more than one loop instance. – Yakk - Adam Nevraumont Sep 18 '17 at 14:44
  • @Yakk Not with the same content right to the colon... The question was "I want something shorter", you provided something longer, which is not what I asked for. I will not add anything else to the discussion. – IceFire Sep 18 '17 at 14:48
  • 2
    @IceFire But your question is relevant to future readers and their specific needs may differ from yours. – Galik Sep 18 '17 at 15:13
  • This is a bit more concise and easier to understand coming from other languages I would argue. The higher rated solutions are more terse but also don't compile for me (MSVC). – perustaja Dec 14 '20 at 01:30