samedi 14 décembre 2019

C++ template metaprogramming help required (version less than 17, preferably 11 please)

I have some C++ and std library experience, and have even written a couple of simple templated functions but - like many others, it seems - template metaprogramming fries my brain.

I want to produce a templated function that parses a std::string for a small range of legal values. It needs to return a different type depending on what is found in the string or an error code if the string does not match any of the legal forms. For example valid string could be:

  • a) numeric single value e.g. "42"
  • b) single non-numeric string e.g. "anything"
  • c) comma-separated list of a) e.g. "13,42,666"
  • d) comma-separated list of b) e.g. "anything,you,want"

Different instantiations would "expect" a certain type and produce an error on a failed match, for example if I want c) and find an otherwise-valid d) then: error, and vice versa. Obviously when a valid match is found, the return type will be different for each.

I'm thinking the return value should be a pair<uint32_t errorcode,T> where T is:

  • a) uint32_t
  • b) std::string
  • c) std::vector<uint32_t>
  • d) std::vector<std::string>

At the highest level of abstraction what I want to do is:

instantiation 1:

if(expecting numeric && (number or list_of_numbers)) f( n | n1,n2,n3...) else error

instantiation 2:

if(expecting string && (string or list_of_strings)) f( s | s1,s2,s3...) else error

I think I'm going to need #include <type_traits> and probably std::is_arithmetic but I just cant "get" the concept and syntax of getting the template to "branch" depending on whether the Expected type is numeric.

Getting more concrete, I'm starting with something like:

template<typename ReturnType, typename Expected>
pair<uint32_t,ReturnType> parseInput(std::string input,std::function<void(ReturnType)> f){
    if(!initalvalidation(input)) return std::make_pair<999, ? >; // Exclude total garbage... ? = don't care as long as its a valid ReturnType

    /*compile-time-if ?? */  *if* is_numeric(Expected){
        ReturnType result;
        result=parseInputForNumbers(input); // will return an empty ReturnType if invalid
        return make_pair<(result.size() > 0 ? 0:123),result>; // 123 = bad numeric format
        // obvs that won't work for uint32_t as it has no size() function, so again...HOW?
    }
    else {
        ... similar for strings
    }
}

I know it isn't going to look like an if / else block , but that's the only way I can explain it!

I do hope this all makes some kind of sense!

Finally, I don't want or need help with parsing, how to decide at runtime whether something is numeric etc I ONLY want help / advice re the structure / syntax of the template function.

Aucun commentaire:

Enregistrer un commentaire