41 votes

Omettre le type de retour en C ++11

J'ai récemment trouvé moi-même à l'aide de la macro suivante avec gcc 4.5 en C++11 mode:

#define RETURN(x) -> decltype(x) { return x; }

Et l'écriture de fonctions comme ceci:

template <class T>
auto f(T&& x) RETURN (( g(h(std::forward<T>(x))) ))

J'ai fait cela pour éviter le désagrément d'avoir à écrire efficacement le corps de la fonction deux fois, et d'avoir conserver les modifications dans le corps et le type de retour de la synchronisation (qui à mon avis est un désastre).

Le problème est que cette technique ne fonctionne que sur une seule ligne fonctions. Alors, quand j'ai quelque chose comme ceci (alambiquée exemple):

template <class T>
auto f(T&& x) -> ...
{
   auto y1 = f(x);
   auto y2 = h(y1, g1(x));
   auto y3 = h(y1, g2(x));
   if (y1) { ++y3; }
   return h2(y2, y3);
}

Puis-je mettre quelque chose d'horrible dans le type de retour.

En outre, chaque fois que j'ai mise à jour de la fonction, je vais avoir besoin de changer le type de retour, et si je ne change pas correctement, j'ai obtiendrez une erreur de compilation si j'ai de la chance, ou à l'exécution d'un bogue dans le pire des cas. Avoir à copier et coller des modifications à deux endroits et de les garder synchronisés je ressens n'est pas une bonne pratique.

Et je ne peux pas penser à une situation où j'avais envie d'un cast implicite sur le retour au lieu d'un cast explicite.

Il y a sûrement une façon de demander au compilateur de déduire cette information. Quel est le point de le compilateur garder un secret? Je pensais que C++11 a été conçu de manière telle répétition ne serait pas nécessaire.

23voto

emsr Points 4616

Il semblerait que g ++ 4.8 obtienne une implémentation de la déduction de type retour automatique. Le correctif a été mis en place par Jason Merrill, qui envoie également un document pour C ++ - 1Y pour la fonctionnalité. La fonctionnalité est disponible avec -std = c ++1y.

Je joue toujours avec.

11voto

Martin v. Löwis Points 61768

La justification de ce comportement est donnée dans le projet, 8.3.5p12:

Une fuite-retour-type est le plus utile pour un type qui serait plus compliqué de préciser avant l' demande de déclaration-id:

template <class T, class U> auto add(T t, U u) -> decltype(t + u);

plutôt que de

template <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);

Donc, ce n'est vraiment fait pour simplifier le cas où le référent pour les noms de paramètre permet de.

Si vous supposez que le C++ peut toujours déduire le type de retour des fonctions à partir de la fonction du corps: ce n'est pas voler. C'est un but de C++ (et C) afin de permettre la modularité en séparant la déclaration de la mise en œuvre, de sorte que, au point de l'appeler, vous ne pouvez pas avoir le corps de la fonction. Toutefois, l'appelant a besoin de connaître les types de paramètres et le type de retour de chaque fonction/méthode appelée.

7voto

Gravis Points 522

Si vous essayez simplement de définir le type de retour, d'en faire un argument de modèle. De cette façon, vous pouvez modifier tout ce qui concerne le type de retour sans changer la fonction. Vous pouvez mettre une valeur par défaut type de retour si vous voulez comme dans cet exemple.

template <class R = int, class T>
R f(T&& x)
{
   ...
   return h2(y2, y3);
}

Le code ci-dessous montre l'efficacité du produit.

LE CODE DE DÉMONSTRATION:

#include <iostream>
#include <iomanip>

template <class T, class S>
T h2(T& x, S& y)
{
  return x + y;
}

template <class R = int, class T>
R f(T& x)
{
  auto y2 = x;
  auto y3 = x;
  return h2(y2, y3);
}

int main(int argc, char** argv)
{
  int x = 7;
  std::string str = "test! ";

  auto d = f<double>(x);
  auto i = f(x); // use default type (int)
  auto s = f<std::string>(str);

  std::cout << std::fixed << std::setprecision(4);
  std::cout << "double: " << d << std::endl;
  std::cout << "int: " << i << std::endl;
  std::cout << "string: " << s << std::endl;

  return 0;
}

SORTIE:

double: 14.0000
int: 14
string: test! test!

Malheureusement, exactement la fonctionnalité que vous recherchez n'existe pas (encore) et ne fait pas partie du C++0x spec. Toutefois, il est possible que ce peut être une partie du C++1x spec lorsqu'il est rédigé. jusqu'alors, s'en tenir à des modèles.

6voto

Ben Voigt Points 151460

EDIT: oups, je viens de réaliser qu'il y a une différence de portée entre la fuite-retour-type de prescripteur et de l'instruction return. Plus précisément:

auto f(int a)
{
    char r[sizeof(f(a))+1];
    return r;
}

Kaboom!


La réponse précédente:

Il est malheureux que la langue ne pas fournir une syntaxe pour le compilateur déduire le type de retour, dans ce cas, car il est trivial de montrer que l'inférence est possible.

Plus précisément, nous parlons du cas où il y a exactement une instruction de retour à l'intérieur de la fonction.

Indépendant de l'endroit où dans la fonction que l'instruction return est, ou du degré de complexité du code précédent est, il devrait être clair que la transformation suivante est possible:

return (ugly expression);

en

auto return_value = (ugly expression);
return return_value;

Si le compilateur peut déduire le type d' return_value (et selon le C++0x règles, il le peut), puis le type inféré de return_value peut être choisi comme type de retour de la fonction.

Il me semble donc qu'une modification de C++0x où la fuite de retour spécificateur de type ne devrait être exigée que lorsque la multiplicité de déclarations de retour n'est pas exactement un serait possible et de résoudre le problème.

3voto

Peng Wang Points 29

Je suis d'accord avec Yttrill. Le type de retour de la déduction a déjà été prouvé à être une option réalisable dans la pratique des langages comme Haskell, et depuis C++ a déjà réalisé "auto", c'est juste un pas de plus pour atteindre le type de retour de la déduction. Cette déduction doit qui se passe au moment de la spécialisation, pas de définition de modèle, puisque les informations du type réel fourni le modèle est nécessaire. La séparer de la déclaration et la définition n'est plus une pratique courante en C++ générique, parce que le modèle du corps doivent être écrits dans les fichiers d'en-tête, et donc le modèle de corps presque toujours aller avec le modèle des déclarations. Dans les situations où il y a plusieurs instructions return et les types d'entre eux ne correspondent pas, le compilateur peut heureusement rapport en cas d'erreur. En résumé, le type de retour de la déduction est tout à fait possible en C++, si le comité le souhaite. Et c'est TRÈS important, parce que la duplication de l'écriture manuelle des types de retour empêche l'utilisation généralisée des petites générique des fonctions d'assistance, ce qui est une pratique courante fonctionnelle et la programmation générique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X