Workaround to return uncovered object without moving ctor

In my API, I have a function that returns std::istringstream.
std::istringstreamclass is not copied, but supports moving like this on the corresponding compiler, there is no problem returning the local one std::istringstream.

However, on gcc 4.9 there is no support for moving std::istringstream. Is there a workaround that I can use this std::istringstreamwithout changing the API from the user's point of view?

The workaround suggested here by using unique_ptr<std::istringstream>will change the semantics of the API.

+4
source share
3 answers

Answering my own question for completeness and future reference.

The goal was to find a workaround for the gcc error (<5), where it std::istringstreamdoes not provide a ctor move that will work in cases where I want to return an un-copyable and (bugly-) immutable stream.
As mentioned in the comments, I can actually change my function signature (at least to gcc <5) to return a proxy object that allows you to copy or move without changing the API for the code used for new / other compilers.

, , - std::istringstream, API, copy-ctor, std::istringstream - . -.

.
:

#if !defined(__GNUC__) || (__GNUC__ >= 5)
   using string_stream = std::istringstream;
#else
    // Until GCC 5, istringstream did not have a move constructor.
    // stringstream_proxy is used instead, as a workaround.
   class stringstream_proxy
   {
   public:
      stringstream_proxy() = default;

      // Construct with a value.
      stringstream_proxy(std::string const& value) :
         stream_(value)
      {}

      // Copy constructor.
      stringstream_proxy(const stringstream_proxy& other) :
         stream_(other.stream_.str())
      {
         stream_.setstate(other.stream_.rdstate());
      }

      void setstate(std::ios_base::iostate state) { stream_.setstate(state); }

      // Stream out the value of the parameter.
      // If the conversion was not possible, the stream will enter the fail state,
      // and operator bool will return false.
      template<typename T>
      stringstream_proxy& operator >> (T& thing)
      {
         stream_ >> thing;
         return *this;
      }


      // Get the string value.
      std::string str() const { return stream_.str(); }

      std::stringbuf* rdbuf() const { return stream_.rdbuf(); }

      // Check the state of the stream. 
      // False when the most recent stream operation failed
      operator bool() const { return !!stream_; }

      ~stringstream_proxy() = default;
   private:
      std::istringstream stream_;
   };
   using string_stream = stringstream_proxy;
#endif
0

std::istringstream, .

, . , .

unique_ptr. , , std::unique_ptr<std::istringstream>, , istringstream. .


rvalue. :

struct MyApiClass {

    std::istringstream&& get_stream() {
        return std::move(*_stream);
    }

private:
    std::unique_ptr<std::istringstream> _stream;
};

, , :

std::istringstream&& stream = myApiClass.get_stream();

// use stream as long as myApiClass exists

, , :

std::istringstream stream = myApiClass.get_stream();

// use stream normally

, . , .

0

move/copy , return braced-init-list:

class C {
    C() = default;
    C(const C&) = delete;
    C(C&&) = delete;
};

C make_C() { return {}; }

int main() {
    C&& c = make_C();
}

, , std::istringstream .

:

struct myIStringStream : std::istringstream
{
    myIStringStream () = default;
};

myIStringStream make_istringstream()
{
    return {};
}

int main()
{
    std::istringstream&& iss = make_istringstream();
}

0
source

Source: https://habr.com/ru/post/1658101/


All Articles