2010-06-08 18 views
8
temporaires

Pouvez-vous s'il vous plaît me expliquer la différence entre le mécanisme des éléments suivants:C++ rvalue dans modèle

int function(); 

template<class T> 
void function2(T&); 

void main() { 
    function2(function()); // compiler error, instantiated as int & 

    const int& v = function(); 
    function2(v); // okay, instantiated as const int& 
} 

est mon raisonnement correct par rapport à l'instanciation? pourquoi n'est pas instancié en tant que const T&?

Merci

Répondre

3

Parce que function renvoie une valeur non constante. Seuls les objets peuvent être const, car ils stockent un état qui pourrait être modifié s'il n'était pas const. Ce que vous retournez là n'est pas un objet, mais une valeur pure. Conceptuellement, ils ne sont pas modifiables (comme les constantes d'énumération, par exemple), mais ils ne sont pas constatifs (comme, encore une fois, les constantes d'énumération).

+2

@aca Pour être plus précis, [les valeurs hors classe ont toujours des types cv-non qualifiés] (http: // stackoverflow.com/questions/2169932/non-class-rvalues-toujours-have-cv-unqualified-types) ;-) Pour les types-classes, il y a une distinction entre rvalues ​​modifiables et const rvalues, donc en général, le 'const' est * pas * superflu! Vous pouvez appeler des méthodes non-const sur des valeurs modifiables et ainsi modifier les objets sous-jacents. Par exemple, 'std :: string (" bonjour ") .append (" monde! ")'. – fredoverflow

+0

@FredOverflow yep bon point. Notez que les valeurs de tableau sont qualifiées de la même manière (la norme dit qu'elles ne le sont pas, mais elles ne le sont pas - vous ne pouvez écrire 'struct A {const int a [1];}; .. A(). A [0] = 0;' dans la plupart des compilateurs (sauf dans comeau, où vous pouvez) - mais si vous supprimez le 'const', vous pouvez (il y a eu des questions sur usenet et ailleurs à ce sujet - aucune solution n'a encore été trouvée). class/non-array rvalue n'est pas un objet Les rvalues ​​type-classe/type tableau sont des objets, donc const a du sens pour eux (voir foot-note sur 4.1/1 dans la norme) –

+0

@FredOverflow je me demande ce que @aca Est-ce qu'il a retiré son commentaire? –

0

Dans cette ligne

function2(function()); 

après le retour de fonction2, l'argument selon lequel passe à elle pourrait avoir son changement de valeur, mais étant donné que la fonction() retourne et il est juste affecté à une variable temporaire , mais ce qui arriverait à cette variable temporaire après qu'elle soit hors de portée est le problème, c'est pourquoi les plaintes du compilateur.

0

Pour compiler le premier appel, il est nécessaire de définir function2 avec le paramètre T & & - il s'agit de rvalue, référence à un objet temporaire. Dans le second appel, v est la référence lvalue, c'est OK. Si votre compilateur ne prend pas en charge les références rvalue, le premier appel peut être compilé uniquement avec le paramètre T, sans référence.

2

Je pense que vous pourriez être confus entre rvalues ​​et le qualificateur de const. function renvoie un rvalue non-const temporaire de type int, de sorte que le compilateur déduit T comme étant int, comme il le devrait. Comme vous le faites remarquer, vous pouvez lier un temporaire à un const ref (C++ 03 12.2/5), mais le compilateur n'ajoutera pas de qualificatifs cv pour rendre un appel de fonction bien formé. Puisque vous ne pouvez pas contrôler la fonction de modèle, il existe deux façons de contourner cela (en plus de la solution que vous avez publiée).

(1) paramètres du modèle explicite: function2<const int>(function())

(2) cv retour se qualifier: const int function();

Ces deux solutions sont bien formées. (1) semble la meilleure solution, à mon humble avis, puisque (2) est non conventionnel et stupide. Edit: En fait, le type déduit peut être plus qualifié en cv que l'argument pour un argument de modèle ref, mais seulement si la déduction de type échoue autrement (C++ 03 14.8.2.1/3). Dans ce cas, la déduction de type n'échoue pas, mais aboutit à un appel de fonction mal formé (SFINAE ne s'applique pas, car la spécialisation de la fonction de template elle-même n'est pas malformée). Si l'intention de l'auteur du modèle était de ne pas modifier l'argument, il doit être déclaré comme argument de référence const, donc cela peut être un bogue dans la bibliothèque de templates, ou il peut modifier l'argument, auquel cas vous allez échouer là où la fonction tente de modifier l'argument. Editer: Comme le souligne FredOverflow, les valeurs hors classe sont toujours non qualifiées par le standard 3.10/9. Donc (2), qui fonctionne sous gcc 4.3, est en fait un bogue du compilateur (gcc < 4.5, d'après FredOverflow).

+1

Il n'y a aucune différence entre la fonction int () 'et' const int function() ', car [les valeurs non classifiées ont toujours des types cv-non qualifiés] (http://stackoverflow.com/questions/2169932/non-class-rvalues-always-have-cv-unqualified -les types). – fredoverflow

+0

@FredOverflow. Idéalement non, mais c'est différent de gcc;) – academicRobot

+0

@aca Hm? Le problème mentionné dans le thread lié a été corrigé dans le dernier compilateur g ++. – fredoverflow