Question

Suppose I have a class whose internal data representation is, for example, an std::string:

class my_type {
   std::string m_value;
   ...
};

Would it be fine if I can "move out" the internal representation of my_type? Such ability would be done in a manner like:

class my_type {
   std::string m_value;

public:
   operator std::string() && {
       // NOTE:           ^^ ref qualifier for r-value

       return std::move(m_value);
       // Explicitly  do std::move is used because ref-qualifiers don't apply
       //    to data members (m_value would still be an l-value), and (N)RVO
       //    would be crazy for the compiler to apply here.
   }
};

...

my_type val;
std::string str1 = std::move(val);
std::string str2 = a_func_that_returns_my_type();

LIVE EXAMPLE

Specific questions:

  1. Is moving out internal representation a BadIdea™? (e.g. leaky implementation?)

  2. Am I abusing the use of (implicit) conversion operator? If so, should I use an explicit one? Example:

    std::string str = std::move(val).get_str();   // Or auto instead of explicit std::string
                                                  // Is this a GoodIdea™?
    

    or

    auto str = val.move_str_out();
    
  3. Should I only define it if there's an existing conversion operator/function for l-values?

  4. Is what I'm trying to achieve here be considered as premature optimization?


For some background info, please see:

Was it helpful?

Solution

Is moving out internal representation a BadIdea™?

I used a similar idea as an escape hatch in my text class to allow the user to perform unfettered manipulation of the underlying bytes for performance or whatever else reasons, without having the invariants of my text class being enforced constantly. This essentially lets you do things on step 2 with intermediate results that would violate the invariants of the class without actually violating them. Putting the representation back in must obviously enforce the invariants again, though.

These semantics are fine for me because my class is explicitly meant as an invariant enforcer over a specific representation.

So I wouldn't say it's a BadIdea™. As long as the member is left in a valid state that obeys the class's invariants, it's fine.

(e.g. leaky implementation?)

It doesn't have to. Since the contents are moved out, the client will never know if it actually came from the class's innards. It could simply be a new string you created in the operator. The internals are still encapsulated fine.

Am I abusing the use of (implicit) conversion operator? If so, should I use an explicit one?

Implicit conversions tend to interact with other features in all sorts of bad ways. I'd avoid them whenever possible. I prefer the explicit member function design. It makes clear what is being moved, and prevents accidents :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top