2017-06-21 3 views
7

[conv]/4:[expr.unary.op]/9 semble impliquer que l'opérateur `(!)` N'a pas pu être appliqué au type A ci-dessous. Mais compilateurs en désaccord avec cette

Certaines constructions linguistiques exigent que l'expression soit converti en une valeur booléenne. Une expression e apparaissant dans un tel contexte est dit être converti en contextuellement bool et est bien formée si et que si la déclaration bool t(e); est bien formée, pour une variable temporaire inventées t (11,6).

Considérons maintenant l'extrait ci-dessous. Il ne compile pas, ni dans clang, GCC ou VS.

struct A{ bool operator!() { return true; } }; 
int main(){ 
    A a; 
    bool t(a); 
} 

Ainsi, à partir de [conv]/4 nous concluons que le type A est pas contextuellement converti en bool.

[expr.unary.op]/9:

L'opérande de l'opérateur de négation logique ! est contextuellement converti en bool (Article 7); sa valeur est true si l'opérande converti est false et false sinon. Le type du résultat est bool.

Ma compréhension du paragraphe ci-dessus est que l'opérande de l'opérateur de négation logique ! doit être converti en contextuellement bool. Nous venons de conclure que le type A est et non converti contextuellement en bool. Par conséquent, à partir de [expr.unary.op]/9, nous pouvons dire que le code suivant doit pas compiler. Mais il le fait, en clang, GCC et VS.

Que manque-t-il?

+3

Ce n'est pas un opérateur de négation logique, c'est la fonction membre 'A :: operator!', C'est ma supposition de toute façon. Je crois que c'est la même chose avec 'operator,', l'opérateur de virgule a une signification inhérente même sans surcharge, mais est bien défini quand il est surchargé –

+0

Essayez de changer 'bool t (a);' à bool t (! a); 'dans votre 1er exemple. Comme dans comment le compilateur peut-il deviner qu'il doit appliquer 'operator!'. –

+4

[Clause \ [expr \] définit les effets des opérateurs appliqués aux types pour lesquels ils n'ont pas été surchargés.] (Http://eel.is/c++draft/expr#3.sentence-1) – cpplearner

Répondre

7

[expr] dans son ensemble applique aux opérateurs intégrés:

article [expr] définit les effets des opérateurs lorsqu'ils sont appliqués à des types pour lesquels ils ne sont pas surchargées.

La définition dans [expr.unary.op] est tout simplement la définition du intégréoperator!. En outre, [over.match.oper] décrit comment rechercher les opérateurs surchargées:

Pour un opérateur unaire @ avec un opérande d'un type dont la version cv-est non qualifiée T1, [...], trois ensembles de fonctions candidats, membre désigné candidats, candidats non-membres et candidats intégrés, sont construits comme suit: [...]

Pour !a, vous auriez deux candidats: votre surcharge A::operator!() et intégré défini dans [over.built]:

Il existe également des fonctions d'opérateur candidats de la forme

bool operator!(bool); 

Pour la sélection de la résolution intégrée de surcharge, le type doit être converti contextuellement en bool& dagger; comme votre argument le suggère. Cependant, ce candidat n'est pas viable - mais l'opérateur membre surchargé est.


& dagger;T.C. est sur le dessus comme d'habitude, soulignant cwg issue 1919 qui indique qu'un type que est contextuellement convertible en bool ne devrait toujours pas utiliser le operator! intégré en raison d'un problème de formulation. Bien que gcc et clang le permettent (ce qui est ce que nous voulons tous arriver, probablement).

+0

Mais notez [le principal numéro 1919] (https://wg21.link/CWG1919). –

+1

@ T.C. Vous ne cessez jamais d'étonner. Johannes a apparemment soumis tous les problèmes fondamentaux. – Barry