error: passing 'const A' as 'this' argument of 'void A::hi()' discards
qualifiers [-fpermissive]
I don't understand why I'm getting this error, I'm not returning anything just passing the reference of the object and that is it.
#include <iostream>
class A
{
public:
void hi()
{
std::cout << "hi." << std::endl;
}
};
class B
{
public:
void receive(const A& a) {
a.hi();
}
};
class C
{
public:
void receive(const A& a) {
B b;
b.receive(a);
}
};
int main(int argc, char ** argv)
{
A a;
C c;
c.receive(a);
return 0;
}
#edit
I fixed it using const correctness but now I'm trying to call methods inside of the same method and I get the same error, but the weird thing is that I'm not passing the reference to this method.
#include <iostream>
class A
{
public:
void sayhi() const
{
hello();
world();
}
void hello()
{
std::cout << "world" << std::endl;
}
void world()
{
std::cout << "world" << std::endl;
}
};
class B
{
public:
void receive(const A& a) {
a.sayhi();
}
};
class C
{
public:
void receive(const A& a) {
B b;
b.receive(a);
}
};
int main(int argc, char ** argv)
{
A a;
C c;
c.receive(a);
return 0;
}
error: passing 'const A' as 'this' argument of 'void A::hello()'
discards qualifiers [-fpermissive]
error: passing 'const A' as 'this' argument of 'void A::world()'
discards qualifiers [-fpermissive]
Your hi method is not declared as const inside your A class. Hence, the compiler cannot guarantee that calling a.hi() will not change your constant reference to a, thus it raises an error.
You can read more about constant member functions here and correct usage of the const keyword here.
// **const object can call only const member function()**
// **Modified Code**
#include <bits/stdc++.h>
using namespace std;
class A {
public:
void hi() const {
std::cout << "hi." << std::endl;
}
};
class B {
public:
void receive(const A& a) {
a.hi();
}
};
class C {
public:
void receive(const A& a) {
B b;
b.receive(a);
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
A a;
C c;
c.receive(a);
return 0;
}
As already mentioned, one option is to make hi method const-qualified.
Another option is to use const_cast at the time of calling the hi method like so
A& ref = const_cast <A&>(a);
ref.hi();
Related
Consider the following code which works as expected:
#include <iostream>
#include <functional>
struct foo
{
std::function<int()> get;
};
struct bar
{
int get()
{
return 42;
}
};
int main()
{
foo f;
bar b;
f.get = std::bind(&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
return 0;
}
Now, let's assume that bar::get() is a const member function:
#include <iostream>
#include <functional>
struct foo
{
std::function<int()const> get;
};
struct bar
{
int get() const
{
return 42;
}
};
int main()
{
foo f;
bar b;
f.get = std::bind(&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
}
Using GCC 9.2, this snipped throws the following compiler error:
main.cpp:6:31: error: field 'get' has incomplete type 'std::function<int() const>'
6 | std::function<int()const> get;
| ^~~
In file included from /usr/local/include/c++/9.2.0/functional:59,
from main.cpp:2:
/usr/local/include/c++/9.2.0/bits/std_function.h:128:11: note: declaration of 'class std::function<int() const>'
128 | class function;
| ^~~~~~~~
I fail to understand why foo::get has incomplete type.
Could somebody point me towards the right direction for understanding this behavior and "fixing" it accordingly?
I have the need to bind a const member function to a function pointer.
int()const is an abominable type.
std::function<int()const> is not a type, because it doesn't match the only defined specialisation
namespace std {
template< class R, class... Args >
class function<R(Args...)> { ... };
}
Just use std::function<int()>.
The const bit only makes sense for member functions. You've already bound bar::get to an instance b to save it as a std::function.
As mentioned by #KamilCuk:
The constness is checked at std::bind, not at std::function
You don't need to pass explicit const to std::function. Just use your older prototype: std::function<int()>. It will work if you don't have const overload (that mean, you have either one of these int bar::get() or int bar::get() const) for the same member function (Otherwise, you need to type cast explicity).
Actually, your function (int bar::get() const) will be having a signature like this (behind the scenes):
// int bar::get() const
int get(const bar *const this)
{
return 42;
}
// int bar::get()
int get(bar *const this)
{
return 42;
}
If you have overloads and want to bind specific member function, you can do something like this:
typedef int(bar::*fptr)(void) const; // or remove const
std::bind((fptr)&bar::get, &b );
See this:
#include <iostream>
#include <functional>
#include <vector>
struct foo
{
std::function<int()> get;
};
struct bar
{
int get()
{
return 42;
}
int get() const
{
return 50;
}
};
int main()
{
foo f;
bar b;
typedef int (bar::*fptr)(void);
typedef int (bar::*fcptr)(void) const;
f.get = std::bind((fptr)&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
f.get = std::bind((fcptr)&bar::get, &b);
if (f.get())
std::cout << "f.get(): " << f.get() << std::endl;
}
Output:
f.get(): 42
f.get(): 50
std::bind does not pass through constness to the callable. Therefore, the following would work:
struct foo {
std::function<int()> get;
// ^ note there is no 'const'
};
Suppose I have the following setup:
#include <iostream>
#include <map>
using namespace std;
class A
{
public:
A() { val1 = 1;}
~A() { }
private:
int val1;
};
class B
{
public:
B() { val2 = 1;}
~B() { }
int getVal() {return val2;}
private:
int val2;
};
class C : public A, public B
{
int val3;
};
void fun(std::pair<int, B>& p) {
cout << "B val: " << p.second.getVal() << endl;
}
void fun2(B& b) {
cout << "B val: " << b.getVal() << endl;
}
int main(int argc, const char *argv[])
{
map<int, C> m;
m.insert(make_pair(1, C()));
m.insert(make_pair(2, C()));
//fun(*(m.begin())); // <---- Compilation error
fun2(m.at(1)); // Works correctly
return 0;
}
Code compiles successfully and works as expected when I make the call to fun2. However if I uncomment the line fun(*(m.begin()) I get the following compilation error:
a.cpp: In function ‘int main(int, const char**)’:
a.cpp:48:18: error: invalid initialization of reference of type ‘std::pair<int, B>&’ from expression of type ‘std::pair<const int, C>’
fun(*(m.begin()));
^
a.cpp:33:6: error: in passing argument 1 of ‘void fun(std::pair<int, B>&)’
void fun(std::pair<int, B>& p) {
Is there any way to make the compiler handle the second element of std::pair polymorphically?
P.S. Sorry if the title is misleading in any way. Couldn't find a better way of expressing this.
This:
*(m.begin())
evaluates to a nameless temporary object. To bind this to a reference, the reference must be const, so:
void fun(const std::pair<int, B>& p) {
and for that function to call getVal(), that must be const too:
int getVal() const {return val2;}
#include <functional>
#include <iostream>
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int get_num(int i) { return num_;}
void set_num(int i) { num_ = i;}
int num_;
};
int main() {
std::function<int(const Foo *, int)> f_get_num;
f_get_num = &Foo::get_num;
return 0;
}
This will generate a error, error: invalid conversion from ‘const Foo*’ to ‘Foo*’ [-fpermissive] at line f_get_num = &Foo::get_num. Foo::get_num type is int (Foo:: *fp)(int). Can anybody explain it? Thanks.
You cannot call non-const functions on const objects. You can pass const Foo* to f_get_num, but Foo::get_num takes non-const implicit this.
The following two calls are just as illegal:
Foo foo;
Foo const* const_ptr = &foo;
const_ptr->get_num(42);
f_get_num(const_ptr, 42); // results in const_ptr->get_num(42)
You can declare your get_num to be const:
int get_num(int i) const { return num_;}
And then your code will work correctly.
The other way is to make your f_get_num take non-const parameter, but that's not the way to go when your function is a getter and shouldn't modify the object.
std::function<int(Foo*, int)> f_get_num;
f_get_num = &Foo::get_num;
error: passing 'const A' as 'this' argument of 'void A::hi()' discards
qualifiers [-fpermissive]
I don't understand why I'm getting this error, I'm not returning anything just passing the reference of the object and that is it.
#include <iostream>
class A
{
public:
void hi()
{
std::cout << "hi." << std::endl;
}
};
class B
{
public:
void receive(const A& a) {
a.hi();
}
};
class C
{
public:
void receive(const A& a) {
B b;
b.receive(a);
}
};
int main(int argc, char ** argv)
{
A a;
C c;
c.receive(a);
return 0;
}
#edit
I fixed it using const correctness but now I'm trying to call methods inside of the same method and I get the same error, but the weird thing is that I'm not passing the reference to this method.
#include <iostream>
class A
{
public:
void sayhi() const
{
hello();
world();
}
void hello()
{
std::cout << "world" << std::endl;
}
void world()
{
std::cout << "world" << std::endl;
}
};
class B
{
public:
void receive(const A& a) {
a.sayhi();
}
};
class C
{
public:
void receive(const A& a) {
B b;
b.receive(a);
}
};
int main(int argc, char ** argv)
{
A a;
C c;
c.receive(a);
return 0;
}
error: passing 'const A' as 'this' argument of 'void A::hello()'
discards qualifiers [-fpermissive]
error: passing 'const A' as 'this' argument of 'void A::world()'
discards qualifiers [-fpermissive]
Your hi method is not declared as const inside your A class. Hence, the compiler cannot guarantee that calling a.hi() will not change your constant reference to a, thus it raises an error.
You can read more about constant member functions here and correct usage of the const keyword here.
// **const object can call only const member function()**
// **Modified Code**
#include <bits/stdc++.h>
using namespace std;
class A {
public:
void hi() const {
std::cout << "hi." << std::endl;
}
};
class B {
public:
void receive(const A& a) {
a.hi();
}
};
class C {
public:
void receive(const A& a) {
B b;
b.receive(a);
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
A a;
C c;
c.receive(a);
return 0;
}
As already mentioned, one option is to make hi method const-qualified.
Another option is to use const_cast at the time of calling the hi method like so
A& ref = const_cast <A&>(a);
ref.hi();
I'm passing the reference of an object to a function and I used const to indicate that it's read-only method, but if I call another method inside of that method this error occur, even if I'm not passing the reference as argument.
error: passing 'const A' as 'this' argument of 'void A::hello()' discards qualifiers [-fpermissive]
error: passing 'const A' as 'this' argument of 'void A::world()' discards qualifiers [-fpermissive]
#include <iostream>
class A
{
public:
void sayhi() const
{
hello();
world();
}
void hello()
{
std::cout << "world" << std::endl;
}
void world()
{
std::cout << "world" << std::endl;
}
};
class B
{
public:
void receive(const A& a) {
a.sayhi();
}
};
class C
{
public:
void receive(const A& a) {
B b;
b.receive(a);
}
};
int main(int argc, char ** argv)
{
A a;
C c;
c.receive(a);
return 0;
}
Since sayhi() is const, then all functions it calls must also be declared const, in this case hello() and world(). Your compiler is warning you about your const-correctness.