The program reads the number from the flash memory of the external device (integer, 1 byte, unsigned). For its programmatic interpretation, an enumeration is used:

enum BoardType { Classic = 0, Static = 1, Smart = 2 } BoardType t = (BoardType)getBoardType(); 

The problem is visible to the naked eye: the number contained in the memory is not necessarily contained in the enum. And I think that in runtime there is no way to check whether the returned number is correct, but it will be necessary, because 0xFF values ​​are stored in the flash memory in the erased state, and other numbers that were there because of my curved hands can also fall. So, is there a way to check if the returned number is in the enum, and if not, how to programmatically interpret this number?

  • Possible duplicate question: Find out the number of members enum - αλεχολυτ
  • @alexolut, enumeration values ​​are not necessarily in order. In addition, I mentioned that I suspect that this is impossible, so I would like to see alternatives. - maestro
  • In the mentioned topic, the solution for your question is voiced. Those. if the range is continuous, then you can check the boundary points, and if with the "holes", then everything gets complicated. - αλεχολυτ
  • Do not be nonsense. Enums are just meant for another. - avp
  • @avp, do not throw words. Enum designed for another? Then tell me what to use instead of them in this situation. While I see the answer Majestio main candidate for "tick". - maestro

3 answers 3

I would suggest, since we are talking about speed and a small number of commands - use just table transformations. And the table will not be excessively large.

Sample code ( link to ideone ):

 #include <iostream> enum class BoardType : uint8_t { Classic = 0, Static = 1, Smart = 2, Bad = 255 }; BoardType Cast[UINT8_MAX]; // <- сюда просто забить константы -++ // inline BoardType ToEnum(const uint8_t i) { // BoardType Ret = Cast[i]; // if (Ret == BoardType::Bad) throw std::range_error("Беда"); // return Ret; // } // // int main () { // ////// вместо инициализации ниже - /////////////////////////////// for(auto i=0; i<UINT8_MAX; i++) Cast[i] = BoardType::Bad; Cast[0] = BoardType::Classic; Cast[1] = BoardType::Static; Cast[2] = BoardType::Smart; ////////////////////////////////////////////////////////////////// try { std::cout << static_cast<int>(ToEnum(0)) << std::endl; std::cout << static_cast<int>(ToEnum(1)) << std::endl; std::cout << static_cast<int>(ToEnum(2)) << std::endl; std::cout << static_cast<int>(ToEnum(3)) << std::endl; } catch(std::range_error &e) { std::cout << "range_error: " << e.what() << std::endl; } catch(...) { std::cout << "что-то совсем пошло не так" << std::endl; } return 0; } 

Conclusion:

 0 1 2 range_error: Беда 

First, using the ToEnum() function, it is possible to ToEnum() "wrong" values ​​in the exception handling blocks.

Secondly, using the Cast table, simply compare with BoardType::Bad if the exception handling is "annoying".

Thirdly, if there are several dozen "commands", the switch will be worse readable, and perhaps even slower to process.

    By and large, no way. Because it is just a legend for integer values.
    So if you really really need to - then either check the range (if the enumeration is without "gaps", or have a separate set of values ​​and check for presence in it.

    In my opinion, so . (c) Pooh

    • Well, you're a C ++ expert. Is it really nothing at all? C ++ tries to emulate reflection for a long time. For example, how in the answers here does it not work? - Vadim Ovchinnikov
    • @VadimOvchinnikov First, how is this essentially different from what I said? Secondly, you know, there are people who write all kinds of #define begin { and start making C ++ Pascal. Is it worth it? And most importantly - no need to ask how best to keep a microscope to hammer nails. It is necessary to solve the problem with the most appropriate means for this. - Harry
    • Well, isn’t there a beautiful workaround? Suppose you use a different data structure like some kind of "dictionary", etc. How would you solve a problem if you need to store a lot and check for the presence of an element in it? - Vadim Ovchinnikov
    • one
      If the set is small - a vector or an array (ordered, if there is information that we are looking for more often), if there is more, probably set or unordered_set . Perhaps with its own hash. If this set is without gaps, simply by comparison. But again you are asking the wrong question ... For example, as stated by the author, then most likely, his programmatic interpretation will use some kind of switch - and there it is enough to write default . - Harry

    Specifically for your example, you can:

     enum BoardType{ Classic = 0, Static = 1, Smart = 2, NumberOfBoardTypes }; bool isCorrect(BoardType t){ return t >= 0 && t < NumberOfBoardTypes; } 

    Or so:

     enum BoardType{ Classic = 0, Static = 1, Smart = 2, Unknown }; BoardType getBoardType(){ BoardType t = static_cast<BoardType>(42); if(t < 0 || t > Unknown){ t = Unknown; } return t; } 

    UPD: for the case of "holes" in the enum can be done like this:

     enum BoardType{ Classic = 0, Static = 1, Smart = 2 }; std::set<BoardType> boardTypes(){ std::set<BoardType> types; types.insert(Classic); types.insert(Static); types.insert(Smart); return types; } bool isCorrect(BoardType t){ static const std::set<BoardType> types = boardTypes(); return types.count(t); } 
    • Yes, in my opinion, since there is an enumeration, then most likely it has something like a switch or - once the whole byte is an array of appropriate, let's say, interpreters . And you can not check for entry into enum , but either write default , or score incorrect interpreter array with some handler ... In a word, it seems to me that again the question is not how to hammer a nail, but how to hold the microscope correctly. .. - Harry
    • @Harry, man obviously works with iron. It may well be that this value is then transmitted to the equipment. - yrHeTaTeJlb