Is it possible to declare two variables of different types in a for loop?
C++17: Yes! You should use a structured binding declaration. The syntax has been supported in gcc and clang since gcc-7 and clang-4.0 (clang live example). This allows us to unpack a tuple like so:
for (auto [i, f, s] = std::tuple{1, 1.0, std::string{"ab"}}; i < N; ++i, f += 1.5) {
// ...
}
The above will give you:
int i
set to1
double f
set to1.0
std::string s
set to"ab"
Make sure to #include <tuple>
for this kind of declaration.
You can specify the exact types inside the tuple
by typing them all out as I have with the std::string
, if you want to name a type. For example:
auto [vec, i32] = std::tuple{std::vector<int>{3, 4, 5}, std::int32_t{12}}
A specific application of this is iterating over a map, getting the key and value,
std::unordered_map<K, V> m = { /*...*/ };
for (auto& [key, value] : m) {
// ...
}
See a live example here
C++14: You can do the same as C++11 (below) with the addition of type-based std::get
. So instead of std::get<0>(t)
in the below example, you can have std::get<int>(t)
.
C++11: std::make_pair
allows you to do this, as well as std::make_tuple
for more than two objects.
for (auto p = std::make_pair(5, std::string("Hello World")); p.first < 10; ++p.first) {
std::cout << p.second << '\n';
}
std::make_pair
will return the two arguments in a std::pair
. The elements can be accessed with .first
and .second
.
For more than two objects, you'll need to use a std::tuple
for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
std::get<0>(t) < 10;
++std::get<0>(t)) {
std::cout << std::get<1>(t) << '\n'; // cout Hello world
std::get<2>(t).push_back(std::get<0>(t)); // add counter value to the vector
}
std::make_tuple
is a variadic template that will construct a tuple of any number of arguments (with some technical limitations of course). The elements can be accessed by index with std::get<INDEX>(tuple_object)
Within the for loop bodies you can easily alias the objects, though you still need to use .first
or std::get
for the for loop condition and update expression
for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
std::get<0>(t) < 10;
++std::get<0>(t)) {
auto& i = std::get<0>(t);
auto& s = std::get<1>(t);
auto& v = std::get<2>(t);
std::cout << s << '\n'; // cout Hello world
v.push_back(i); // add counter value to the vector
}
C++98 and C++03 You can explicitly name the types of a std::pair
. There is no standard way to generalize this to more than two types though:
for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
std::cout << p.second << '\n';
}
How do I declare several variables in a for (;;) loop in C?
You can (but generally shouldn't) use a local struct type.
for ( struct { int i; char* ptr; } loopy = { 0, bam };
loopy.i < 10 && * loopy.ptr != 0;
++ loopy.i, ++ loopy.ptr )
{ ... }
Since C++11, you can initialize the individual parts more elegantly, as long as they don't depend on a local variable:
for ( struct { int i = 0; std::string status; } loop;
loop.status != "done"; ++ loop.i )
{ ... }
This is just almost readable enough to really use.
C++17 addresses the problem with structured bindings:
for ( auto [ i, status ] = std::tuple{ 0, ""s }; status != "done"; ++ i )
Can I declare variables of different types in the initialization of a for loop?
Yes, that is prohibited. Just as otherwise you cannot declare variables of differing types in one declaration statement (edit: modulo the declarator modifiers that @MrLister mentions). You can declare structs
for (struct { int a = 0; short b = 0; } d; d.a < 10; ++d.a, ++d.b ) {}
C++03 code:
for (struct { int a; short b; } d = { 0, 0 }; d.a < 10; ++d.a, ++d.b ) {}
Of course when all are 0
, you can omit the initializers altogether and write = { }
.
Is there a way to define variables of two different types in a for loop initializer?
Here is a version using boost preprocessor (This is just for fun. For the real-world answer, see @kitchen's one above):
FOR((int i = 0)(int j = 0.0), i < 10, (i += 1, j = 2 * i)) {
}
The first part specifies a sequence of declarations: (a)(b)...
. The variables declared later can refer to variables declared before them. The second and third part are as usual. Where commas occur in the second and third parts, parentheses can be used to prevent them to separate macro arguments.
There are two tricks known to me used to declare variables that are later visible in a compound statement added outside a macro. The first uses conditions, like an if:
if(int k = 0) ; else COMPOUND_STATEMENT
Then k
is visible. Naturally, it always have to evaluate to false
. So it can't be used by us. The other context is this one:
for(int k = 0; ...; ...) COMPOUND_STATEMENT
That's what i'm going to use here. We'll have to watch to only make one iteration of COMPOUND_STATEMENT
. The actual for
loop that does the increment and condition checking has to come at the end, so the appended compound statement appertains to it.
#include <boost/preprocessor.hpp>
#include <iostream>
#define EMIT_DEC_(R,D,DEC) \
for(DEC; !_k; )
#define FOR(DECS, COND, INC) \
if(bool _k = false) ; else \
BOOST_PP_SEQ_FOR_EACH(EMIT_DEC_, DECS, DECS) \
for(_k = true; COND; INC)
int main() {
FOR((int i = 0)(float j = 0.0f), i < 10, (i += 1, j = 2 * i)) {
std::cout << j << std::endl;
}
}
It's creating a bunch of for
statements, each nested into another one. It expands into:
if(bool _k = false) ; else
for(int i = 0; !_k; )
for(float j = 0.0f; !_k; )
for(_k = true; i < 10; (i += 1, j = 2 * i)) {
std::cout << j << std::endl;
}
Is it possible to declare two variables For-Each Loop in C++?
Simple answer is no, you can not do that. This for loop is called for each loop, and structure goes like this:
for each ELEMENT in MAP/ARRAY/VECTOR
do something
If I am correct your intention is to have something like this
in loop
store each element of MAP_A into i and each element of MAP_B in j
It is not possible
Your only solution is:
NOTE: This is for arrays of the same size.
for (int i = 0; i < NumOfElemens; ++i)
int aa = a[i];
int bb = b[i];
// DO SOMETHING
}
You can also shorthand this to:
for (int i = 0, aa = a[0], bb = b[0]; i < NumOfElemens; ++i, aa = a[i], bb = b[i]) {
// DO SOMETHING
}
This also might work, but I do not guaranty that will always work as intendend
for (int i = 0; i < NumOfElemens; aa = a[i], bb = b[i], ++i) {
// DO SOMETHING
}
I used i
for increment and aa
and bb
to store elements.
Type limitation in loop variables in Java, C and C++
This limitation exists because your requirement is fairly unusual, and can be gained with a very similar (and only slightly more verbose) construct. Java supports anonymous code blocks to restrict scope if you really want to do this:
public void method(int a) {
int outerVar = 4;
{
long variable = obj.operation();
for (int i = 0; i < 15; i++) { ... }
}
}
For loop of two variables in Go
You don't have a comma operator to join multiple statements, but you do have multiple assignment, so this works:
package main
import (
"fmt"
)
func main() {
for i, j := 0, 1; i < 10; i, j = i+1, j+1 {
fmt.Println("Hello, playground")
}
}
Related Topics
Operator New Initializes Memory to Zero
Alternative to Itoa() For Converting Integer to String C++
Separating Class Code into a Header and Cpp File
Is Uninitialized Local Variable the Fastest Random Number Generator
Declaring Variables Inside Loops, Good Practice or Bad Practice
Getting a File* from a Std::Fstream
Can You Use 2 or More or Conditions in an If Statement
Programmatically Find the Number of Cores on a Machine
When to Use Inline Function and When Not to Use It
How to Set a Breakpoint on 'Memory Access' in Gdb
C/C++ With Gcc: Statically Add Resource Files to Executable/Library
Linking Static Libraries to Other Static Libraries
How to Implement Aba Counter With C++11 Cas
C++ Static Polymorphism (Crtp) and Using Typedefs from Derived Classes