'this' argument to member function 'select' has type 'const SelectParam', but function is not marked const
Asked Answered
M

3

24

I'm trying to call a function on a polymorphic item. But I get the following error message at compile time:

'this' argument to member function 'select' has type 'const SelectParam', but function is not marked const

the error is shown at the p->selection(*it)

std::set<Tuple>::iterator it;
for (it = tuples.begin(); it != tuples.end();) {
    for (const SelectParam* p: selectionParams) {
        bool successful = p->select(*it);
        if( !successful ) {
            it = tuples.erase(it);
        } else {
            it++;
        }
    }
}

and here's how those classes are defined. (I use to not have all the const and & is there but I put them everywhere I could in hopes that I would make whatever it wanted const but clearly I'm not approaching the problem right since it's not changing anything.

In one of the child classes that is being stored at parent pointer.

bool const select(Tuple const & tup) {
    bool matched = false;
    if (tup[idx] == val) {
        matched = true;
    }
    return matched;
}

In the other child class that is being used with polymorphism

bool const select(Tuple const & tup) {
    bool matched = false;
    if (tup[idx1] == tup[idx2]) {
        matched = true;
    }
    return matched;
}

And finally here's the parent class that's super simple.

class SelectParam {
    public:
    virtual const bool select( Tuple const & t) = 0;
};

Thanks in advance for being willing to help my feeble brain.

Marcello answered 31/5, 2019 at 1:14 Comment(0)
T
29

Indeed, you cannot call a non-const method a const object. But you also cannot call a non-const method through a pointer or reference to a const object (regardless of whether the referred-to object is const or not).

This means that this:

const SelectParam* ptr = whatever();
ptr->select(someTuple);

is ill-formed.

In your case, you've declared a pointer to a const SelectParam here on this line:

for (const SelectParam* p: selectionParams) {

Simply remove the const and it should work :-)

On the other hand, if select is never meant to modify the object, simply mark it as const:

virtual const bool select( Tuple const & t) const = 0;

And your code should also work.

Teodoor answered 31/5, 2019 at 1:21 Comment(0)
V
14

You need to explicitly tell the compiler that your function will not modify any members:

bool const select(Tuple const & tup) const {
Veal answered 31/5, 2019 at 1:20 Comment(0)
F
4

An object declared as const can neither be changed by a const nor a non-const member function (except for constructor and destructor). Even if it is passed by reference. There are two exceptions to this rule:

  1. The constness can be casted away (casting the const away) but is generally not advised.
  2. Class members can be declared using the mutable keyword. These members can be changed through member functions even if the containing object is declared const.

More can be read here:

const object - an object whose type is const-qualified, or a non-mutable subobject of a const object. Such object cannot be modified: attempt to do so directly is a compile-time error, and attempt to do so indirectly (e.g., by modifying the const object through a reference or pointer to non-const type) results in undefined behavior.

As commented by others, one solution would be to add the const keyword to the member function in both its declaration and definition. With that, the function can be called even on const objects.

What is up with this though?

Within a member function, this is a pointer to the current object the function was called on [see].

Futility answered 15/3, 2021 at 20:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.