I have a Node and BinaryTree class:
template<typename Elem>
struct Node {
Elem Key;
Node <Elem>* parent = nullptr;
Node <Elem>* left = nullptr;
Node <Elem>* right = nullptr;
Node(Elem k);
};
template<typename Elem>
Node<Elem>::Node(Elem k):Key{k}{}
template<typename Elem>
class BinaryTree{
public:
class iterator; //Node<Elem>*
iterator root;
void insert(Elem val);
void remove(iterator& z);
};
With class iterator in BinaryTree implemented as:
template<typename Elem>
class BinaryTree<Elem>::iterator{
public:
iterator();
iterator(Node<Elem>* p);
Node<Elem>* curr = nullptr;
iterator& parent(); //set curr = curr->right
iterator& left();
iterator& right();
void setparent(iterator& b);//sets this.curr->parent = b.curr->parent
void setleft(iterator& b);
void setright(iterator& b);
iterator& Parent(); //Creates a new iterator that points to curr->parent and returns a reference to that
iterator& Left();
iterator& Right();
Elem& operator *(); // returns curr->Key
bool operator ==(iterator& b);
bool operator !=(iterator& b);
void operator =(iterator& b);
};
I made a minimum function to be used in the BinaryTree<Elem>::remove(iterator& z)
function, implemented as:
template<typename Elem>
typename BinaryTree<Elem>::iterator & minimum(typename BinaryTree<Elem>::iterator & z) {
while(z.Left().curr != nullptr) {
z.left();
}
return z;
}
The remove function, when it calls minimum()
with z.Right()
as an argument, gives the error C2783 , which states that:
"BinaryTree::iterator &minimum(BinaryTree::iterator &)': could not deduce template argument for 'Elem'"
The remove() function is implemented as:
template<typename Elem>
void BinaryTree<Elem>::remove(iterator& z) {
if (z.Left().curr == nullptr) {
transplant(*this, z, z.Right());//The z.Right() creates a new iterator on the heap, whose curr pointer points to z.curr->right
}
else if (z.Right().curr != nullptr) {
transplant(*this, z, z.Left());
}
else {
iterator y = minimum(z.Right()); //-> This gives the error C2783 and C2762 (no matching overloaded function found)
if (y.Parent() != z) {
transplant(*this, y, z.Right());
y.curr->right = z.curr->right;
y.Right().curr->parent = y.curr;
}
transplant(*this, z, y);
y.curr->left = z.curr->left;
y.curr->left->parent = y.curr;
}
}
There are several contexts in which an argument to a template function is non-deduced. The case where there is a template argument to the left of the ::
(scope resolution operator) is one such case.
In the following cases, the types, templates, and non-type values... do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified.
- The nested-name-specifier (everything to the left of the scope resolution operator
::
) of a type that was specified using a qualified-id...
( Source )
So, in your example, everything to the left of the ::
operator in the function argument is in a non-deduced context:
template<typename Elem>
typename BinaryTree<Elem>::iterator & minimum(
typename BinaryTree<Elem>::iterator & z
^^^^^^^^^^^^^^^^ ^^^^^^^^
non-deduced deduced
)
Deduction fails simply because deduction is not attempted in this case.
Note that there is nothing to deduce on the right side. However, there is in this example:
template <typename Elem>
void foo(std::vector<Elem> const &)
Deduction of Elem
can be performed here because it does not appear to the left of the ::
operator.
The simplest workaround is simply to not care whether this is a BinaryTree<Elem>::iterator
and just accept any type:
template <typename T>
T & minimum(T & z) { ... }
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.