vendredi 18 mai 2018

Deducing the right types when dealing with arrays, pointers and references

I'm writing this templated static data integrity checker and overloading the oprator() to perform the check and return a bool on call.

It's part of an API and only accepts some public enum type as a first template parameter, providing the right validation path for each enum value.

Data to be checked is stored in a struct as follows (cannot be changed):

typedef struct {
    uint8_t sn[12];              
    uint8_t version[9];          
    uint8_t someInt;
} BoardInfo_t;

And the template looks something like this:

#include <regex>
#include <iostream>

enum class BoardInfoItem { sn, version, someInt };

// note: I could use template <auto> here but I'm not allowed c++17 :)
template<typename EnumType, EnumType EnumVal, typename DataType>
struct DataCheck {
    using Item = BoardInfoItem;

    bool operator()(const DataType& src) const {
        static_assert(std::is_same<EnumType, Item>::value, "DataCheck requires BoardInfoItem");

        switch (EnumVal) {
        case Item::sn:
        case Item::version:
            return std::regex_match(reinterpret_cast<const char*>(src), std::regex("[a-z\-\._[:digit:]]+", std::regex::icase));
        case Item::someInt:
            return (*src >= 0 && *src <= 100); // wrong
        default: return false;
        }
    }
};


int main() {
    BoardInfo_t boardInfo = { "12345", "12345", 5 };
    std::cout << DataCheck<BoardInfoItem, BoardInfoItem::sn, decltype(BoardInfo_t::sn)>()(boardInfo.sn); // true!
    std::cout << DataCheck<BoardInfoItem, BoardInfoItem::someInt, decltype(BoardInfo_t::someInt)>()(boardInfo.someInt); // doesn't compile

    return 0;
}

However this overload works:

bool operator()(const DataType* src) const {
    switch (EnumVal) {
    case Item::someInt: return (*src >= 0 && *src <= 100);
    }
}

How do I deal with those multiple DataType and why does the above works?

Aucun commentaire:

Enregistrer un commentaire