Reputation: 33
I'm trying to override the <<
operator but it seems that the compiler doesn't recognize my implementation and instead tries to interpret it as a bit shift.
I've already tried to play around with the parameter types (const T&
, T&
, T
, const T
) to no avail.
#pragma once
template<typename T> class AbstractStack
{
public:
virtual bool Push(const T &) = 0;
}
template <typename T> class ArrayStack : public AbstractStack <T>
{
public:
bool Push(const T&) {
....
}
}
template <typename T> bool operator<<(const AbstractStack<T>* &, const T&) {
return stack->Push(item);
}
int main() {
AbstractStack<int> *stack = new ArrayStack<int>(5);
int a = 2;
stack << a; // <<-- compiler error
return 0;
}
The error reported is:
Error (active) expression must have integral or unscoped enum type Lab10
Error C2296 '<<': illegal, left operand has type 'AbstractStack<int> *'
If I define the same operator acting on the class as a value, it just works...
Upvotes: 3
Views: 399
Reputation: 30606
When overloading operators, at least one of the arguments must be a class or an enum type - basically this allows/limits you to overloading custom types (user defined types).
From the cppreference;
When an operator appears in an expression, and at least one of its operands has a class type or an enumeration type, then overload resolution is used to determine the user-defined function to be called among all the functions whose signatures match the following...
This makes sense in that it disallows you from overloading the built in types; in this case, the pointer and integer you have as arguments.
As you already remarked in the question, the solution is taking your first argument by reference;
template <typename T>
bool operator<<(AbstractStack<T> &, const T&)
{ //...
Given the abstract base class you are looking to use, you could investigate the use of std::shared_ptr
to help manage the resources and make the use of a "pointer" in the overloaded operator (albeit it will be a smart pointer);
template <typename T>
bool operator<<(std::shared_ptr<AbstractStack<T>>&, const T&)
{
return stack->Push(item);
}
int main() {
std::shared_ptr<AbstractStack<int>> stack = std::make_shared<ArrayStack<int>>(5);
int a = 2;
stack << a;
return 0;
}
Upvotes: 3
Reputation: 76245
As others have said, overloading any builtin operator requires an object of a user-defined type; a pointer won't work. And the solution is to use an object instead of a pointer:
template <typename T> bool operator<<(AbstractStack<T>&, const T&) {
return stack.Push(item);
}
and then call it with an object. There's no good reason in the code you've shown to allocate from the free-store; just create an auto object:
int main() {
ArrayStack<int> stack(5);
int a = 2;
stack << a;
return 0;
}
Upvotes: 2