drewpol
drewpol

Reputation: 697

Create method to work as operator

Is it possible in C++ to create custom method which will work as overloaded operator? For example simple class:

class A
{
public:
  A(int val){ x = val;}
  int getInt(){ return (x + 2); }

private:
  int x;
};

How to do method toSpecialString which will, for example, format my returned int in a special way and then return this string (e.g "abc14"). Example:

A a(12);
std::cout << a.getInt().toSpecialString() << std::endl;

As output I'm expecting "abc14". Is something like that possible in C++?

Upvotes: 2

Views: 61

Answers (2)

The Vee
The Vee

Reputation: 11550

Sure, for example

class A
{

  struct ReturnedInt {
    int x;

    // constructor
    ReturnedInt(int x_) : x(x_) { }

    // "transparent" type cast to int
    operator int() { return x; }

    std::string toSpecialString() {
      std::ostringstream oss{};
      oss << "abc" << x;
      return oss.str();
    }
  };

public:
  A(int val){ x = val;}
  ReturnedInt getInt(){ return (x + 2); } // I changed the return type but see the remarks below

private:
  int x;
};

Then

int main () {
  A a{12};
  std::cout << a.getInt() << '\n';
  std::cout << a.getInt().toSpecialString() << '\n';
}

prints

14
abc14

where the former was passed to the cout's operator<< as a plain int (decaying automatically) but in the latter we use the fact that the return value is actually an object. For the same reason as the former line, any function expecting an int will also accept ReturnedInt. Moreover, in the compiled binary this kind of "wrapper" structure should come at zero additional cost.

Note that the inner class can be private (like in my example) if you don't intend to expose it for any other purposes. This does not collide with the fact that it's used as a return type or that its (public) methods are invoked.

Upvotes: 3

R Sahu
R Sahu

Reputation: 206557

a.getInt().toSpecialString() does not work since a.getInt() returns an int. An int is not a class and hence, cannot have a member function.

Possible solutions:

  1. Add toSpecialString() as a member function.

    class A
    {
       ...
    
          std::string toSpecialString()
          {
             return std::string("abc") + std::to_string(getInt());
          }
    };
    

    and use it as:

    a.toSpecialString();
    
  2. Add another class to create a string.

    struct MyStringFormatter
    {
       std::string toSpecialString(int x)
       {
          return std::string("abc") + std::to_string(x);
       }
    };
    

    and use it as:

    MyStringFormatter().toSpecialString(a.getInt());
    

    If necessary, MyStringFormatter can be updated to take an instance of A and return the string.

    struct MyStringFormatter
    {
       std::string toSpecialString(A a)
       {
          return toSpecialString(a.getInt());
       }
    
       std::string toSpecialString(int x)
       {
          return std::string("abc") + std::to_string(x);
       }
    };
    

    and can be used as:

    MyStringFormatter().toSpecialString(a);
    

My recommendation would be to use the second method. It separates class A from the special logic used to format an int.

Upvotes: 1

Related Questions