2

Assume I have a member variable std::vector<std::string> in a class and I want to return it from a member function as an immutable view using a combination of gsl::array_view and gsl::cstring_view. Unfortunately, the following doesn't compile:

class C {
public:
    gsl::array_view<const gsl::cstring_view<>> getVectorOfStrings() const 
    { 
         return _vectorOfStrings; 
    }

private:
    std::vector<std::string> _vectorOfStrings;
};

The reason for this is that there's no container of cstring_view that the array_view can be created from. So my question is: is there a way to use such a construct without explicitly adding something like a member of type std::vector<gsl::cstring_view<>>, which is clearly undesirable?

Edit

It seems to me that such 'transforming' views might be of more general use. Consider having a vector of owning pointers, such as std::vector<std::shared_ptr<T>>, which I'd like to expose to the user of the class as an array_view of raw pointers: gsl::array_view<const T*> without exposing my implementation-defined storage approach. Thoughts?

8
  • With this theoretical array_view of cstring_views, who would own the collection of cstring_views, whose existence is required by the existence of the array_view of the cstring_views? Commented Oct 28, 2015 at 14:25
  • @jaggedSpire Well, that's exactly what I stated in the last paragraph of my question. But perhaps there's a way of some kind of lazy-evaluating array_view which would convert whatever string_view-compatible array value to a string_view on request. I could probably write such a thing, but I thought that perhaps there's a better way. Thus this SO question :) Commented Oct 28, 2015 at 14:44
  • ah. If you want to refer to a non-owning collection of things that can be lightweight-convertible to cstring_views, may I ask why the avoidance of an array_view of std::strings? Commented Oct 28, 2015 at 14:51
  • @jaggedSpire Yeah, that's actually what I have in the code now. But, what if, say, other subclass stores its strings as std::vector<const char*>? It's kind of an 'academic' interest which might result in some contribution to gsl if other people deem it useful (who knows?). Commented Oct 28, 2015 at 15:11
  • The only alternative to those approaches I (with my limited experience :P) can think of would be to just construct a vector of cstring_views and pass it out of the function to be converted as the client code sees fit. If the client needs it in exactly one expression, it can be returned as a temporary and the client can construct an array_view inline. Otherwise, they can just keep the vector and construct array_views from it as needed. Of course you need to construct it every time you need it then, so it'd only make sense if you needed to pass an array_view<cstring_view> into a function Commented Oct 28, 2015 at 15:20

1 Answer 1

1

Per definition, views usually only provide references to existing objects. As a result, there is no way to create a normal array_view<const cstring_view<>> without first creating an matching container like e.g. a vector<const cstring_view<>>.

What you could do however, is to create your own specialization for gsl::array_view<const cstring_view<>>, that creates a cstring_view<> on demand (when the index operator is called and when the iterator is dereferenced). While this would save you a dynamic memory allocation and reduce the memory footprint compared to the naive approach, I don't it's worth the added complexity in most cases.

If you want to follow a generalized approach as described in your edit, you might want to have a look at boost::transform_iterator - either for direct use or as an inspiration for your own generalized transform_array_view class (which I'm sure, would be a welcome addition to the gsl or boost).

Sign up to request clarification or add additional context in comments.

1 Comment

Well, after some more research, it seems to me that the array_view (or span as it is called now) is just not fit by design for this purpose. span expects contiguous storage of some data type, so basically, it could be processed by calling data(). In the end, I used any_range with transformed range adaptor. I still think it might be an interesting discussion, so I will raise a discussion on GSL's github.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.