2
votes

Existe-t-il un moyen de convertir implicitement une classe enum en std :: byte?

J'ai la fonction suivante:

write({
    std::byte(INST::SET_LOW),
    low_byte,
    std::byte(0xFB),
    std::byte(INST::SET_HI),
    hi_byte,
    std::byte(0xFF)
    });

Et je veux l'appeler avec un nombre variable de std::bytes:

std::byte low_byte { 0 };
std::byte hi_byte{ GPIO_PINS::GPIOH0 | GPIO_PINS::GPIOH3 };

write({
    INST::SET_LOW,
    low_byte,
    0xFB,
    INST::SET_HI,
    hi_byte,
    0xFF
    });

( INST et GPIO_PINS sont enum class: byte - faites attention à la différence entre byte code > (en fait unsigned char ) et std :: byte , à cet égard ..)

Mais cela ne compilera pas. Je dois ajuster l'appel comme suit:

uint_fast32_t write(const std::vector<std::byte>& bytes_to_write) const
{
    ...
}

Ma question est de savoir s'il existe un moyen d'éliminer le besoin de ces constructeurs std :: byte (ou static_cast)?

Peut-être un remplacement d'opérateur implicite ou autre?


3 commentaires

Toute cette construction avec une séquence de passage d'octets séparés dans le constructeur du vecteur temporaire semble plutôt suspecte. Pourquoi n'utilisez-vous pas une sorte de structure ou de générateur significatif qui accepterait directement des valeurs telles que INST :: SET_LOW ?


@VTT, pourquoi cela semble-t-il suspect? Je veux passer un nombre variable d'octets. Qu'entendez-vous par «structure ou constructeur significatif»?


Parce que les octets passés n'ont aucune signification.


4 Réponses :


6
votes

"Existe-t-il un moyen de convertir implicitement une classe enum en std :: byte?" - Non.

Les énumérations de type sécurisé n'autorisent pas les conversions implicites vers d'autres types. Vous devez utiliser un casting.

Voir aussi: https://en.cppreference.com/w/cpp/ language / enum


9 commentaires

Pourriez-vous élaborer ou transformer votre réponse en commentaire? Tel quel, cela ressemble vraiment à une opinion.


@YSC En quoi "Non (ça ne peut pas être fait)" ressemble à une opinion? Si cela ne peut pas être fait, cela ne peut pas être fait qui me semble être un fait.


@YSC ce n'est pas une opinion, c'est un fait, à la fois sémantiquement et techniquement.


@YSC J'ai élaboré un peu, mais je pense toujours que "Non" est une réponse acceptable puisque c'est le fait. "Non ... tu ne peux pas faire ça". Ce n'est pas une opinion. C'est un fait. Dit aussi court et simple que possible.


Une déclaration sans explication ni source me regarde. Cela peut être juste, cela peut être faux. Exemple: "les licornes existent". La réponse a été corrigée maintenant :) +1


@SergeyA Il y a une différence inhérente entre ce qu'est quelque chose et ce à quoi quelque chose ressemble . Pour vous, pour moi, comme nous le savons par expérience, Jesper a raison, c'est un fait. Pour quelqu'un qui n'aime pas (comme OP), cela pourrait être les deux. "Un fait est quelque chose qui peut être vérifié et sauvegardé avec des preuves. " . Puisque la déclaration de Jesper peut être étayée par des preuves, je lui ai demandé de le faire. Qu'est-ce qui ne va pas là-dedans?


@YSC Pour mémoire; Je ne pense pas qu’il y ait quelque chose de faux à ce que vous me demandiez d’élaborer. Je pense que c'était inutile , mais ce n'est pas la même chose que faux . Et j'ai fait élaboré comme vous l'avez demandé.


@YSC: " Puisque la déclaration de Jesper peut être étayée par des preuves, je lui ai demandé de le faire. " Non, vous ne l'avez pas fait. Vous avez demandé "Pourriez-vous élaborer ou transformer votre réponse en commentaire?" Si vous vouliez qu'il cite la norme ou fournisse une autre preuve, vous auriez dû le demander spécifiquement. Vous avez dit «élaboré», ce qui pouvait vraiment vouloir dire n'importe quoi.


Tellement de dramaaaaaa. Belle réponse Jesper. Je me tire.



1
votes

Ce n'est pas possible de le faire. Les conversions implicites définies par l'utilisateur doivent se faire via des constructeurs ou des opérateurs de conversion. Mais les constructeurs et les opérateurs de conversion doivent tous deux être des membres de classe, ce que les énumérations, bien sûr, ne peuvent pas avoir.


0 commentaires

3
votes

Le but général d'une classe enum est de ne pas être implicitement convertible en son type sous-jacent (et de définir ses valeurs). Si une conversion implicite est ce dont vous avez besoin, vous devez utiliser une simple énumération ou écrire vous-même les casts.

Vous pouvez créer une énumération implicitement convertible qui agit comme une classe d'énumération en plaçant une énumération régulière dans un espace de noms . De cette façon, ses valeurs sont étendues à l'espace de noms, mais vous obtenez la conversion implicite offerte par une énumération régulière.


0 commentaires

1
votes

Malheureusement, il n'existe aucun moyen de définir un opérateur de conversion pour la classe enum .

Cependant, pour atteindre votre objectif, vous pouvez rendre la fonction d'écriture générique pour permettre de passer des arguments de différents types: p>

template <typename Enum>
uint32_t write(Enum e)
{
    static_assert(std::is_enum<Enum>::value && sizeof(e) == 1, "");
    // write enum
}

uint32_t write(std::byte b)
{
    // write enum
}

template <typename ...Args>
uint32_t write(Args... args)
{
    return (write(args) + ...);
}

(je suppose que la fonction renvoie le nombre d'octets en cours d'écriture, utilisez donc + comme opérateur de repli)


2 commentaires

Je ne peux pas combiner les valeurs d'énumération INST , les valeurs numériques et std :: byte de cette façon: le code uint32_t write (Args ... args) La fonction s'attend à ce que les valeurs soient du même type. Je veux dire que je ne peux pas appeler: write (INST :: SET_LOW, low_byte / * de type std :: byte * /, 0xFB) car les variables d'entrée sont de types différents.


@Tar, pourquoi pas? Args peut être une liste de différents types. Voici un exemple compilable: godbolt.org/z/qM1A6G