2010-10-09 5 views
11

Après la lecture approfondie de ISO/IEC 14882, Programming language – C++ je ne sais toujours pas pourquoi const est nécessaire pour la conversion implicite à un type défini par l'utilisateur avec un constructeur unique argument comme lePourquoi const pour conversion implicite?

suivant
#include <iostream> 

class X { 
public: 
    X(int value) { 
     printf("constructor initialized with %i",value); 
    } 
} 

void implicit_conversion_func(const X& value) { 
    //produces "constructor initialized with 99" 
} 

int main (int argc, char * const argv[]) { 
    implicit_conversion_func(99); 
} 



À partir de l'article 4 ligne 3

Une expression e peut être implicitement convertie en un type T si et seulement si la déclaration T t = e; est bien formé, pour une variable temporaire inventée t (8.5). Certaines constructions de langage requièrent qu'une expression soit convertie en une valeur booléenne. Une expression e apparaissant dans un tel contexte est dite convertie contextuellement en bool et est bien formée si et seulement si la déclaration bool t (e); est bien formé, pour une variable temporaire inventée t (8.5). L'effet de la conversion implicite est le même que l'exécution de la déclaration et de l'initialisation, puis l'utilisation de la variable temporaire comme résultat de la conversion. Le résultat est une lvalue si T est un type de référence lvalue (8.3.2), et une valeur rvalue sinon. L'expression e est utilisée comme lvalue si et seulement si l'initialisation l'utilise comme lvalue.

Après que je trouve la section sur les initialiseurs liés à des types définis par l'utilisateur dans 8.5 ligne 6

Si un programme appelle à l'initialisation par défaut d'un objet d'un type const qualifié T, T doit être un type de classe avec un constructeur par défaut fourni par l'utilisateur.

Enfin, je fini à 12.3 ligne 2 sur les conversions définies par l'utilisateur qui dispose

conversions définies par l'utilisateur sont appliquées que si elles sont sans ambiguïté (10.2, 12.3.2).

Inutile de dire que 10.2 et 12.3.2 n'ont pas répondu à ma question.

  1. Quelqu'un peut-il faire la lumière sur l'effet const a sur les conversions implicites?
  2. Est-ce que l'utilisation de const rend la conversion "uniboque" par 12.3 ligne 2?
  3. Est-ce que const affecte d'une manière ou d'une autre la valeur de lvalue par rapport à la valeur mentionnée à la section 4?
+1

N'aimes-tu pas le C++? –

Répondre

13

Il n'a pas vraiment beaucoup à faire avec la conversion étant implicite. En outre, il n'a pas vraiment beaucoup à faire avec conversions. Il s'agit vraiment de rvalues ​​ par rapport à lvalues ​​.

Lorsque vous convertissez 99 taper X, le résultat est un rvalue. En C++, les résultats des conversions sont toujours des valeurs (sauf si vous convertissez en type de référence). Il est illégal dans C++ d'attacher des références non-const à rvalues.

Par exemple, ce code ne compilera pas

X& r = X(99); // ERROR 

parce qu'il tente d'attacher une référence non-const à un rvalue. D'autre part, ce code est bien

const X& cr = X(99); // OK 

parce qu'il est tout à fait correct de fixer une référence const à un rvalue.

La même chose se produit également dans votre code. Le fait qu'il implique une conversion implicite est un peu à côté de la question. Vous pouvez remplacer la conversion implicite avec un explicite un

implicit_conversion_func(X(99)); 

et se retrouver avec la même situation: avec const il compile, sans const il ne fonctionne pas.

Encore une fois, le seul rôle joué par la conversion (explicite ou implicite) est que cela nous aide à produire une valeur. En général, vous pouvez produire un rvalue d'une autre manière et exécuter le même problème

int &ir = 3 + 2; // ERROR 
const int &cir = 3 + 2; // OK 
+0

"_Lorsque vous convertissez 99 en type X, le résultat est un rvalue._" Non. ** Un rvalue est une expression. ** Convertir '99' en' X' donne un objet temporaire. – curiousguy

+0

@curiousguy: Alors que le concept de "rvalue" est fermement attaché à l'expression, le terme "rvalue" peut être utilisé pour désigner l'expression elle-même ainsi que le résultat qu'elle produit. La norme de langage utilise beaucoup plus souvent le concept de "résultat de valeur" que celui de "expression de valeur". (De toute évidence, les deux sont en fait destinés à faire référence à la même chose). De plus, la spécification du langage indique clairement et explicitement en 5.2.3 que le résultat du cas de style fonctionnel est une valeur. Période. Le fait qu'il s'agisse également d'un «objet temporaire» n'est guère pertinent ici. – AnT

+0

Pourriez-vous expliquer ce que signifie "rvalue"? – curiousguy

0

Par section 5.2.2 paragraphe 5, lorsqu'un argument d'une fonction est de const type de référence, une variable temporaire est automatiquement introduit si nécessaire. Dans votre exemple, le résultat rvalue de X(99) doit être placé dans une variable temporaire afin que cette variable puisse être passée par const référence à implicit_conversion_func.

+0

"_le rvalue 99 doit être placé dans une variable temporaire afin que cette variable puisse être passée par (const) une référence au constructeur de X_" Non. Le paramètre du constructeur est passé par valeur; il n'y a pas de référence constante à 'int', et pas de temporaire avec la valeur 99." _La sémantique de la création d'un non-const temporaire serait dans tous les cas plutôt confuse_ "Qu'en est-il de' std :: string() = "Bonjour, monde "'? – curiousguy

+0

@curiousguy Bon point - Je pense que j'ai mal lu l'OP. Le temporaire est un 'const X' initialisé en construisant avec' 99' comme argument, pas comme 'const int'. L'essentiel de cela reste cependant: un 'const' temporaire est créé pour satisfaire l'argument' const & '. –

Questions connexes