1
votes

Falsifier vrai ↔ faux

Cette question n'a aucune utilité pratique! J'ai posé cette question uniquement parce que je suis curieux!

Il existe un moyen en C ++ de falsifier true comme false en écrivant quelque part #define true false , puis partout true dans le code sera considéré comme false . Mais je cherche un moyen de falsifier true comme false et false comme true en même temps:

#define temptrue true
#define true false
#define false temptrue

Cela ne fonctionne pas, et essayer de "sauvegarder" l'original true non plus:

#define true false
#define false true


7 commentaires

C'est un comportement indéfini. «Ça ne marche pas» est à prévoir.


Merci @MSalters. En dehors de ma réponse (bien sûr ;-)) c'est le seul commentaire ou réponse sensé sur cette page.


@Bathsheba Ma réponse et la réponse acceptée également soulignent que cela est indéfini et inutile.


La redéfinition des mots-clés de la langue n'est pas autorisée. Cela rend le programme fondamentalement invalide.


Voir la section: 17.6.4.3 Noms réservés Paragraphe 2 Une unité de traduction ne doit pas #define ou #undef noms lexiquement identiques à ** mots-clés **, aux identifiants listés dans le Tableau 2, ou à les jetons d'attribut décrits en 7.6. Voir la section 2.11 Mots-clés pour les mots-clés qui incluent vrai et faux.


@jxh La norme est claire sur la question. Voir la section citée ci-dessus. La discussion dans stackoverflow que vous liez n'est pas pertinente pour cette discussion et parle de la mauvaise section de la norme. J'ai mentionné la bonne partie de la norme et il est clair que c'est illégal, il n'y a pas d'interprétation.


@MartinYork: Vous citez une section qui est toujours régie par [contraintes] , et [contraintes.overview] dit qu'elle ne s'applique que lors de l'utilisation de la bibliothèque standard.


4 Réponses :


1
votes

Ceci n'a évidemment aucune utilité pratique et n'est pas un C ++ valide, mais ce qui suit fait l'affaire:

static constexpr auto fake_true = false;
static constexpr auto fake_false = true;

#define true fake_true
#define false fake_false

Le simple fait d'utiliser des littéraux numériques (par exemple 1 et 0) peut sembler plus simple mais entraînera sémantique différente dans les situations où le type compte (par exemple, résolution de surcharge).


0 commentaires

2
votes

Peut-être quelque chose comme ça?

#define false static_cast<bool>(1)
#define true  static_cast<bool>(0)

Concernant un comportement indéfini:

Ceux qui disent qu'il n'est pas défini font probablement référence à la réponse à cette question: Est-il légal de redéfinir un mot-clé C ++?

Cependant, si vous n'utilisez pas la bibliothèque C ++ standard , la restriction citée ne s'applique pas (bravo à Bathsheba et Martin York).

16.5.4.1 [contraintes.overview]
Le paragraphe 16.5.4 décrit les restrictions sur les programmes C ++ qui utilisent les fonctionnalités de la bibliothèque standard C ++.
...
16.5.4.3.2 [macro.names] ...
Une unité de traduction ne doit pas #define ou #undef des noms lexiquement identiques aux mots-clés, ...
Brouillon C ++ 2020


4 commentaires

C'est joli mais malheureusement le comportement n'est pas défini.


Mis à jour avec la dernière version de la norme afin que je l'utilise correctement (ma copie était ancienne de quelques versions). open-std.org/jtc1/sc22/ wg21 / docs / papers / 2020 / n4861.pdf Voir la section 16.5.4.3.2 Noms de macro : Paragraphe 2 Une unité de traduction ne doit pas #define ou #undef noms lexicalement identiques aux mots-clés, aux identifiants listés dans le tableau 4, ou aux jetons d'attribut décrits en 9.12, sauf que les noms probables et improbables peuvent être définis comme des macros de type fonction (15.6).


@jhx: Le paragraphe 1 traite explicitement de l'inclusion des fichiers d'en-tête de la bibliothèque standard. Le paragraphe 2 n'impose aucune restriction et s'applique tout le temps. La simple liaison avec la bibliothèque standard invoque 16.5.4.1 n'a pas besoin d'inclure des fichiers d'en-tête. Vous devez établir un lien avec la bibliothèque standard pour exécuter l'application (sauf si vous êtes un petit sous-ensemble de systèmes embarqués).


@MartinYork: Juste pour s'assurer que ces objections et clarifications ont un contexte. Vous citez une section qui est toujours régie par 16.5.4 [contraintes] , et 16.5.4.1 [contraintes.overview] dit qu'elle ne s'applique que lors de l'utilisation de la bibliothèque standard. Cela a été clarifié dans la réponse. Merci pour l'aide.



1
votes

utilisez des variables constexpr plutôt que de changer le comportement de true et false.

static constexpr bool TRUE = false;
static constexpr bool FALSE = true;


1 commentaires

Minutieux. Les macros TRUE et FALSE sont définies dans de nombreux fichiers d'en-tête C qui peuvent être inclus dans des fichiers d'en-tête C ++.



2
votes

Le comportement lors de la tentative de #define un mot clé C ++ n'est pas défini. Ne le faites pas!

Ce n'est pas si joli, mais

static constexpr bool true_ = false;
static constexpr bool false_ = true;

est probablement le mieux que vous puissiez faire.


3 commentaires

@KonradRudolph: Vous gagnez, et je vais vous déjeuner la prochaine fois que je serai à Cambridge. Merci.


Ce déjeuner devra attendre, d'autant plus que je suis actuellement également coincé à Londres (je travaille toujours à Cambs mais j'ai déménagé à Camden l'année dernière).


C'est la seule suggestion juridiquement valable.