Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to pointer issue

I have a question regarding references to pointers, or a pointer reference or whatever you want to call it, but first some code. First, an abstract compare function template class:

template <class T> struct BinaryTrivalent {
    virtual BinaryTrivalent<T>* clone() const = 0;
    virtual int operator()(const T& lhs, const T& rhs) const = 0;
    int compare(const int a, const int b) const {
        if (a < b)
            return LESS_THAN;
        else if(a == b)
            return MATCH;
        return MORE_THAN;
    }
};

And the actual use of it:

struct NodePCompare : public BinaryTrivalent<Node*> {
    NodePCompare* clone() const { return new NodePCompare(*this); }
    int operator()(const Node*& lhs, const Node*& rhs) const {
        return compare(lhs, rhs);
    }
};

The template works fine on actual types but it doesn't seem to recognise operator as I expect it to and tells me that NodePCompare is abstract.
I've come across this problem in the past but I gave up trying to figure out what the problem was and just wrapped the pointer in another type.
I could do the same thing now but I would like to understand what the real issue is.
I've been reading up on what exactly *& is supposed to mean in this context and, unless I haven't understood correctly, this should work fine.
This link helped a bit in understanding it: http://markgodwin.blogspot.co.il/2009/08/c-reference-to-pointer.html

Ideas anyone?

like image 551
Itamar Bitton Avatar asked Aug 28 '26 03:08

Itamar Bitton


1 Answers

Your problem is that the signature doesn't really match.

It should be this:

int operator()(Node* const & lhs, Node* const & rhs) const {
    return compare(lhs, rhs);
}

The problem is where the const ends up applying. You could accomplish the same thing by saying typedef Node * base_T_arg_t; in the private section of your class and then saying this:

int operator()(const base_T_arg_t &lhs, const base_T_arg_t &rhs) const {
    return compare(lhs, rhs);
}

Basically, the const before the * doesn't bind to the type of the pointer as a whole, it binds to the type Node.

The return type of clone is a red herring for two reasons. First, a function signature does not include its return type. So you are most definitely creating a definition of clone that matches the original signature and will therefore override it.

But, if your return types didn't match the compiler would normally give you an error. Except there's a principle called 'contravariance' that allows return types that are references or pointers to be references or pointers to a derived class when the function is overridden.

After all, a pointer to a derived type is freely convertible to a pointer to a base type. They're, in a sense, equivalent.

like image 99
Omnifarious Avatar answered Aug 29 '26 18:08

Omnifarious



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!