Je jouais avec auto
en std::pair
. Dans le code ci-dessous, la fonction f
est censée retourner un std::pair
type qui dépend d'un paramètre de modèle.
Un exemple pratique:
EXEMPLE 1
template <unsigned S>
auto f()
{
if constexpr (S == 1)
return std::pair{1, 2}; // pair of ints
else if constexpr (S == 2)
return std::pair{1.0, 2.0}; // pair of doubles
else
return std::pair{0.0f, 0.0f}; // pair of floats
}
Cela fonctionne avec gcc 9.2, gcc 10.0, clang 9.0 et clang 10.0.
Ensuite, je voulais écrire explicitement le type de retour en tant que std::pair
pour des raisons de clarté:
EXEMPLE 2
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return {1, 2};
/* ... */
}
Gcc 9.2 / 10.0 et clang 9.0 / 10.0 n'ont pas réussi à le compiler.
gcc 9.2
error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return
D'après le dernier message d'erreur, gcc 9.2 semble croire que std::pair<auto, auto>
c'est un int
. Comment cela peut-il être expliqué?
gcc 10.0
error: returning initializer list
Cette erreur est compréhensible, cependant, je m'attendais à ce que le constructeur de std::pair
soit invoqué, ou y a-t-il quelque chose qui me manque ici?
clang 9.0 et 10.0
'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'
Ok, clang n'aime rien de tout ça. D'après le deuxième message d'erreur, il semble que clang pense également que le type de retour est int
.
Enfin, pour corriger l'erreur obtenue lors de la compilation avec gcc 10.0, j'ai décidé de retourner std::pair
explicitement un :
EXEMPLE 3
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return std::pair{1, 2};
/* ... */
}
clang 9.0 et 10.0
Comme avant, mais avec en plus:
no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'
Ici, Clang pense toujours que nous retournons un int
?
gcc 9.2
Pareil qu'avant.
gcc 10.0
Ça marche!
Je suppose que certaines fonctionnalités doivent encore être implémentées, ou dans l'une des situations décrites ci-dessus, existe-t-il un compilateur qui est bon et l'autre mal? À mon avis, l'exemple 2 devrait fonctionner. Ou non?
auto x = {1, 2};
travaux, mais uniquement si tous les types sont identiques.int
. Ce n'est pas queint
c'est un espace réservé dans les messages d'erreur; le compilateur pense vraiment que c'est unint
. (Pour rendre cela plus clair, gcc aurait probablement dû dire "en supposant int" à un moment donné.)std::pair __f{1,2};
fonctionne.std::optional f() { return 4; }
travail.