Pass a string Recursively without Recreation

后端 未结 2 1943
抹茶落季
抹茶落季 2020-12-07 06:01

I answered a question here: https://stackoverflow.com/a/28862668/2642059 Where I needed to use recurrence to step through a string. I wanted to use a cons

相关标签:
2条回答
  • 2020-12-07 06:41

    Write your own array_view<T>. It is a few dozen lines of code.

    Use std::find to replace both algorithms. In one case, use reverse iterators. (or write a range-based find and range-based backwards)

    Use {T*,T*} ctor to recurse.

    array_view<const char> foo(array_view<const char> bar)
    

    Here is a primitive array_view<T>:

    template<class T>
    struct array_view {
      using mutable_T = typename std::remove_reference<T>::type;
      // 3 primitive functions:
      T* begin() const { return b; }
      T* end() const { return e; }
      array_view(T* s, T* f):b(s), e(f) {};
      // everything else based on them:
      size_t size() const { return end()-begin(); }
      array_view(T* s, size_t l):array_view(s,s+l) {}
      array_view():array_view(nullptr,  nullptr) {}
      // repeat next 3 for string, array, initializer list, C array as required:
      template<class A>
      array_view( std::vector<T,A>& v ):array_view(v.data(), v.size()) {}
      // may not compile for non-const T, but that is ok  you get an error:
      template<class A>
      array_view( std::vector<mutable_T,A>const & v ):array_view(v.data(), v.size()) {}
      // in a better world, you'd SFINAE remove the above from consideration
      // consider it for your next iteration of array_view.
      // conversion to containers:
      template<class A>
      explicit operator std::vector<mutable_T,A>() const {
        return convert_to< std::vector<mutable_T, A> >();
      }
      template<class C>
      C convert_to() const {
        C retval(begin(), end());
        return retval;
      }
    
      // utility functions:
      T& front() const { return *begin(); }
      T& back() const { return std::prev(*end()); }
      // Also rbegin, rend, and whatever else you find you are missing
    
      // inspired by std::experimental:
      void pop_front() { *this = {std::next(begin()), end()}; }
      void pop_back() { *this = {begin(), std::prev(end())}; }
      // but I find direct use of `view = {x,y}` almost as good
      // these kind of operations are the ONLY ones that are non-const
      // remember this is a view.  If you want a view of const data, make it
      // an array_view<const T>, not a const array_view<T>.  It really works
      // out better.
    private:
      T* b
      T* e;
    };
    

    the above sample code is not tested.

    0 讨论(0)
  • 2020-12-07 06:42

    string_view from the library fundamentals TS might be one idea, support is available in GCC.

    The interface is virtually identical to string

    #include <experimental/string_view>
    using std::experimental::string_view;
    
    string_view foo(const string_view& bar){
        auto start = bar.find('(') + 1;
    
        return start == string_view::npos + 1 ? bar : foo(bar.substr(start, bar.find_last_of(')') - start));
    }
    

    The last line could also be

    return start ? foo(bar.substr(start, bar.find_last_of(')') - start)) : bar;
    

    Although they're both pretty cryptic.

    0 讨论(0)
提交回复
热议问题