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
Since you're defining space_type
as an alias (i.e. 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