vesii
vesii

Reputation: 3128

Convert int into a generic template type

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

Answers (2)

JaMiT
JaMiT

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

hyde
hyde

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

Related Questions