简体   繁体   中英

C++ <<operator overloading with same type

I'm writing a method to print some spaces in std::cout , I know there are other ways using the standard library to achieve the same objective. Anyway, I used a typedef to store the number of spaces and an overloading of the << operator. But my overloading isn't called at all because my typedef is interpreted as an unsigned int.

So how can I tell to the compiler to call my function instead ?

class MyClass {
private: 
  typedef unsigned int space_type;

public: 
  std::ostream& operator<< (std::ostream& _os, space_type _n_spaces) {
    for (int _C = 0; _C < _n_spaces; _C++) 
      _os << " ";
    return _os;
  }

  void PrintNumbers(char _a, char _b) {
    space_type spaces = 5;
    std::cout << _a << spaces << _b << std::endl;
  }
}

int main () {
  MyClass class_instance;
  class_instance.PrintNumbers('K', 'X');

  std::cin.get();
  return 0;
}

This is the expected output:

K     X

This is the output I obtain:

K5X  // 5 is interpreted as an unsigned int, so my overloaded function 
     // isn't called, instead is called the std overloading with unsigned int

Typedef doesn't create new type, it just creates alias of existing type. Possbile you could use something like this:

struct SpaceType {
    int space_cnt;
};
...
std::ostream& operator<< (std::ostream& _os, SpaceType _n_spaces) {
    for (int _C = 0; _C < _n_spaces.space_cnt; _C++) 
      _os << " ";
    return _os;
  }
...  
SpaceType spaces = { 5 };
std::cout << _a << spaces << _b << std::endl;

Since you're defining space_type as an alias (ie typedef) and not a type, it is not distinguishable from int , and the compiler will issue an error if you attempted to overload operator(std::ostream&, int) .

But what you're doing is defining a class member:

std::ostream& operator<< (std::ostream& _os, space_type _n_spaces)

When you define operators as class members, the first argument to the operator is (implicitly) an instance of the class. So in principle, that could only be called with:

MyClass m;
m << ???

But here is a problem: an operator function called using infix notation can only have two parameters, and in the case of a member operator function, the first argument is implicit. m << x can only be implemented by MyClass::operator<<(decltype(x)) .

In short, you can only implement this with a non-member operator<< and the second argument to that overload must be a user type. So the following will work fine:

struct space_t {
   unsigned x;
   space_t(unsigned x) : x(x) {}
   operator unsigned() const { return x; }
};

std::ostream& operator<< (std::ostream& os, space_t n) {
  for (unsigned i = 0; i < n; ++i) os << " ";
  return os;
}

See it on ideeone

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM