Est-il possible de déclarer deux variables de types différents dans le corps d'initialisation d'une boucle for en C++?
Par exemple:
for(int i=0,j=0 ...
définit deux entiers. Puis-je définir un int
et un char
dans le corps d'initialisation? Comment cela serait-il fait?
Pas possible, mais vous pouvez faire:
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
Ou, limitez explicitement la portée de f
et i
à l'aide de crochets supplémentaires:
{
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
}
Non - mais techniquement, il y a un moyen de contourner le problème (pas que je l'utilise réellement à moins d'y être forcé):
for(struct { int a; char b; } s = { 0, 'a' } ; s.a < 5 ; ++s.a)
{
std::cout << s.a << " " << s.b << std::endl;
}
C++ 17 : Oui! Vous devez utiliser un déclaration de liaison structurée . La syntaxe est prise en charge dans gcc-7 et clang-4.0 ( exemple de clang live ). Cela nous permet de décompresser un tuple comme ceci:
_for (auto [i, f, s] = std::Tuple{1, 1.0, std::string{"abc"}}; i < N; ++i) {
// ...
}
_
Ce qui précède vous donnera:
int i
_ défini sur _1
_double f
_ défini sur _1.0
_std::string s
_ défini sur _"abc"
_Assurez-vous de _#include <Tuple>
_ pour ce type de déclaration.
Vous pouvez spécifier les types exacts à l'intérieur de Tuple
en les saisissant tous comme je le sais avec le _std::string
_, si vous souhaitez nommer un type. Par exemple:
_auto [vec, i32] = std::Tuple{std::vector<int>{3, 4, 5}, std::int32_t{12}}
_
C++ 14 : vous pouvez faire la même chose que C++ 11 (ci-dessous) en ajoutant un type _std::get
_. Ainsi, au lieu de std::get<0>(t)
dans l'exemple ci-dessous, vous pouvez avoir std::get<int>(t)
.
C++ 11 : std::make_pair
vous permet de le faire, ainsi que std::make_Tuple
pour plus de deux objets.
_for (auto p = std::make_pair(5, std::string("Hello World")); p.first < 10; ++p.first) {
std::cout << p.second << std::endl;
}
_
_std::make_pair
_ renverra les deux arguments dans un _std::pair
_. Les éléments sont accessibles avec _.first
_ et _.second
_.
Pour plus de deux objets, vous devrez utiliser un _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) << std::endl; // cout Hello world
std::get<2>(t).Push_back(std::get<0>(t)); // add counter value to the vector
}
_
_std::make_Tuple
_ est un modèle variadique qui construira un tuple d'un nombre quelconque d'arguments (avec quelques limitations techniques bien sûr). Les éléments sont accessibles par index avec std::get<INDEX>(Tuple_object)
Dans le corps de la boucle for, vous pouvez facilement créer un alias sur les objets, même si vous devez toujours utiliser _.first
_ ou _std::get
_ pour la condition de boucle for et l'expression de mise à jour.
_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 << std::endl; // cout Hello world
v.Push_back(i); // add counter value to the vector
}
_
C++ 98 et C++ 03 Vous pouvez nommer explicitement les types d'un _std::pair
_. Il n'y a pas de moyen standard de généraliser ceci à plus de deux types:
_for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
std::cout << p.second << std::endl;
}
_
Vous ne pouvez pas déclarer plusieurs types dans l'initialisation, mais vous pouvez affecter à plusieurs types E.G.
{
int i;
char x;
for(i = 0, x = 'p'; ...){
...
}
}
Il suffit de les déclarer dans leur propre champ.
Voir " Y a-t-il un moyen de définir des variables de deux types dans une boucle for?? " pour une autre façon impliquant l'imbrication de plusieurs boucles for. L’avantage de l’autre solution par rapport à la "struct astuce" de Georg est qu’elle (1) vous permet d’avoir un mélange de variables locales statiques et non statiques et (2) d’avoir des variables non-copiables. L'inconvénient est qu'il est beaucoup moins lisible et peut être moins efficace.
Je pense que la meilleure approche est réponse de xian .
mais...
Cette approche est sale, mais peut résoudre du tout version.
alors, je l’utilise souvent dans des fonctions macro.
for(int _int=0, /* make local variable */ \
loopOnce=true; loopOnce==true; loopOnce=false)
for(char _char=0; _char<3; _char++)
{
// do anything with
// _int, _char
}
Il peut également être utilisé pour declare local variables
et initialize global variables
.
float globalFloat;
for(int localInt=0, /* decalre local variable */ \
_=1;_;_=0)
for(globalFloat=2.f; localInt<3; localInt++) /* initialize global variable */
{
// do.
}
Bon exemple: avec fonction macro.
(Si meilleure approche ne peut pas être utilisé car il s'agit d'une macro for-loop)
#define for_two_decl(_decl_1, _decl_2, cond, incr) \
for(_decl_1, _=1;_;_=0)\
for(_decl_2; (cond); (incr))
for_two_decl(int i=0, char c=0, i<3, i++)
{
// your body with
// i, c
}
if (A* a=nullptr);
else
for(...) // a is visible
Si vous voulez initialiser avec 0
ou nullptr
, vous pouvez utiliser cette astuce.
mais je ne le recommande pas à cause d'une lecture difficile.
et cela ressemble à un bug.
Définir une macro:
#define FOR( typeX,x,valueX, typeY,y,valueY, condition, increments) typeX x; typeY y; for(x=valueX,y=valueY;condition;increments)
FOR(int,i,0, int,f,0.0, i < 5, i++)
{
//...
}
Rappelez-vous simplement que vos portées variables ne seront pas dans la boucle for de cette façon non plus.