Named parameter string formatting in C++

后端 未结 6 2032
甜味超标
甜味超标 2021-02-07 08:55

I\'m wondering if there is a library like Boost Format, but which supports named parameters rather than positional ones. This is a common idiom in e.g. Python, where you have a

6条回答
  •  春和景丽
    2021-02-07 09:51

    Well I'll add my own answer as well, not that I know (or have coded) such a library, but to answer to the "keep the memory allocation down" bit.

    As always I can envision some kind of speed / memory trade-off.

    On the one hand, you can parse "Just In Time":

    class Formater:
      def __init__(self, format): self._string = format
    
      def compute(self):
        for k,v in context:
          while self.__contains(k):
            left, variable, right = self.__extract(k)
            self._string = left + self.__replace(variable, v) + right
    

    This way you don't keep a "parsed" structure at hand, and hopefully most of the time you'll just insert the new data in place (unlike Python, C++ strings are not immutable).

    However it's far from being efficient...

    On the other hand, you can build a fully constructed tree representing the parsed format. You will have several classes like: Constant, String, Integer, Real, etc... and probably some subclasses / decorators as well for the formatting itself.

    I think however than the most efficient approach would be to have some kind of a mix of the two.

    • explode the format string into a list of Constant, Variable
    • index the variables in another structure (a hash table with open-addressing would do nicely, or something akin to Loki::AssocVector).

    There you are: you're done with only 2 dynamically allocated arrays (basically). If you want to allow a same key to be repeated multiple times, simply use a std::vector as a value of the index: good implementations should not allocate any memory dynamically for small sized vectors (VC++ 2010 doesn't for less than 16 bytes worth of data).

    When evaluating the context itself, look up the instances. You then parse the formatter "just in time", check it agaisnt the current type of the value with which to replace it, and process the format.

    Pros and cons: - Just In Time: you scan the string again and again - One Parse: requires a lot of dedicated classes, possibly many allocations, but the format is validated on input. Like Boost it may be reused. - Mix: more efficient, especially if you don't replace some values (allow some kind of "null" value), but delaying the parsing of the format delays the reporting of errors.

    Personally I would go for the One Parse scheme, trying to keep the allocations down using boost::variant and the Strategy Pattern as much I could.

提交回复
热议问题