Reputation: 3128
I have the following function in TreeWrapper.h
:
template<typename Key, typename Data, class Compare=std::less<Key>>
class TreeWrapper{
// .............
public:
void addNode(Key &key, Data &data) {
currentAVLTree.addNode(key, data);
}
I would like to use the following command:
currentGroup.addNode(group, group.getTotal());
But getTotal
returns int
and not Data
. Is it possible to convert it somehow? I thought that Data
is a generic type that get anytype. Why it does not work?
EDIT:
In TreeWrapper.h
the important part:
template<typename Key, typename Data, class Compare=std::less<Key>>
class TreeWrapper {
AVLTree<Key, Data, Compare> currentAVLTree;
public:
void addNode(Key &key, Data &data) {
currentAVLTree.addNode(key, data);
}
};
In the AVLTree.h
:
template<typename Key, typename Data, class Compare=std::less<Key>>
class AVLTree {
Compare keyCompare;
AVLNode<Key, Data> *root;
int length;
public:
bool addNode(Key &key, Data &data) {
// impl
}
};
In the GroupWrapper
:
class GroupWrapper {
private:
TreeWrapper<Group, Group, compareGroup> currentGroup;
public:
void addGroup(Group group) {
currentGroup.addNode(group, group.getTotal());
}
};
But I get an error: Parameter type mismatch: Expression must be lvalue
on group.getTotal()
and it suggests to change Data
to int
. Why?
Upvotes: 0
Views: 149
Reputation: 16853
I thought that
Data
is a generic type that get anytype.
Not quite. It is true that Data
represents a generic type, but that view holds only when defining the template. When a template is used, it is instantiated. Part of instantiation involves providing concrete replacements for the generic template parameters. For that instantiation, the replacement is fixed, no longer generic.
For example, look at the declaration of your TreeWrapper
template.
template<typename Key, typename Data, class Compare=std::less<Key>>
class TreeWrapper
One way to use and instantiate this template is with a line like:
TreeWrapper<Group, Group, compareGroup> currentGroup;
Effectively, this takes the TreeWrapper
template and replaces every instance of "Key
" with "Group
", every instance of "Data
" with "Group
", and every instance of "Compare
" with "compareGroup
". The result is the definition of the type of currentGroup
.
Consequentially, the signature of addNode
becomes the following:
void addNode(Group &key, Group &data)
You can try to call currentGroup.addNode(group, group.getTotal())
, but since getTotal()
returns an int
(not convertible to Group &
), the signature does not match.
A solution for (just) this call is the suggested change of Data
's concrete replacement. If you were to use
TreeWrapper<Group, int, compareGroup> currentGroup;
then the signature of addNode
would be
void addNode(Group &key, int &data)
and the call to currentGroup.addNode(group, group.getTotal())
would almost* match. However, this would presumably mess something else up, unless you had decided to use Group
as the tree's data type without understanding what type of data the tree would hold.
* "Almost" because this would bind a temporary to a non-const reference. Since addNode
sounds like it has no business changing either of its parameters, they should be constant references (or non-reference values), which would then make your call work.
void addNode(const Key &key, const Data &data)
This should be done in both TreeWrapper
and AVLTree
.
Upvotes: 2
Reputation: 62797
You are passing non-const reference, which is why it complains about lvalue, which means a value which can be on the left side of an assignment. A function call needs to return a reference if you want to put it on the left side, and yours returns just plain int.
Changing getTotal to return a reference would probably be a very bad idea, so two solutions remain.
Add const at least for data:
bool addNode(Key &key, const Data &data)
Or pass a value:
bool addNode(Key &key, Data data)
Consider same changes for key.
Upvotes: 0