Martel
Martel

Reputation: 2734

Get iterator for const reference

I'm developing a class that must return an iterator with the begin() method. Also, I have to develop a function that receives a const reference of this class and iterates over it.

When I try to get an iterator from this method, I have the following compilation error: "the object has type qualifiers that are not compatible with the member function."I can't understand why this error appears.

Here is the code that I have written:

// ------------ class Neuron -------------
class Neuron { ... };
// ---------------------------------


// ------------ class AbstractLayer -------------
class AbstractLayer {
public:

    class Iterator : public std::iterator<std::input_iterator_tag, Neuron> {
        public:
            Iterator(Neuron *neurons) : _neurons(neurons) {}
        private:
            Neuron *_neurons;
    };

    virtual Iterator begin() = 0;
    virtual const Iterator begin2() = 0;
};
// ----------------------------------------


// ------------ class Layer -------------
class Layer : AbstractLayer {

public:
    Layer(){};
    Iterator begin(){ return Iterator(_neurons); }
    const Iterator begin2(){ return (const Iterator)begin(); }

private:
    Neuron *_neurons;
    int _size;
};
// --------------------------------


// ------------ Method where the problem is -------------------
void method(const AbstractLayer &layer){
    // Error in both methods: 
    // "the object has type qualifiers that are not compatible with the member function."
    layer.begin();
    layer.begin2();
}
// -------------------------------------------------------------

Upvotes: 3

Views: 2092

Answers (4)

AndyG
AndyG

Reputation: 41092

Your function accepts a const AbstractLayer which means that only const member functions can be called on it. However, begin and begin2 are not const. In fact, given that only begin2 returns a const Iterator, it wouldn't make sense to try and call begin anyway in this method.

Change

virtual const Iterator begin2() = 0;

to

virtual const Iterator begin2() const = 0;

and

const Iterator begin2()

to

const Iterator begin2() const

Finally, returning a const Iterator is actually meaningless in your code, as the const is discarded on account of an rvalue being returned. Regardless, you shouldn't need to perform casting to const Iterator when you call begin; just return an Iterator and the compiler will take care to make it const.

Finally, your Layer class needs to derive publicly from AbstractLayer:

class Layer : public AbstractLayer

Live Demo

Upvotes: 0

mefyl
mefyl

Reputation: 263

In method, the layer argument is const which prevents you from calling non-const methods on it. If you take layer by non-const reference (void method(AbstractLayer &layer)), you will be able to call both methods.

You should probably provide a const begin method that returns a const_iterator so you can iterate over a const AbstractLayer.

Upvotes: 0

SergeyA
SergeyA

Reputation: 62553

You do not need begin and begin2. What you need is two versions of begin - const and non-const. A const one would return const iterator. You also might want a cbegin (const only) which would always return const iterator.

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409146

In the method function, layer references a constant object. That means you can only call functions marked as const. Like e.g.

class AbstractLayer {
public:
    ...
    virtual const Iterator begin() const = 0;  // <- Note use of `const` here
    ...
};

Upvotes: 4

Related Questions