My getters are giving me a nonstandard and cannot convert error - c++

I'm learning as I'm going but while writing these getters for a stat page for a character, I'm getting an error that it is nonstandard, it cant convert the const, and it tells me to add a & "to create a pointer to a member"
I have tried making them pointers with *, I have tried not making them const, making them public, adding any headers that my be missing.
These are the only lines of many that are giving the errors. It produces about 30 errors.
inline const double& getX() const { return this->getX; }
inline const double& getY() const { return this->getY; }
inline const std::string& getName() const { return this->name; }
inline const int& getLevel() const { return this->level; }
inline const int& GetExpNext() const { return this->expNext; }
inline const int& getHP() const { return this->hp; }
inline const int& getStamina() const { return this->stamina; }
inline const int& getDamageMin() const { return this->getDamageMin; }
inline const int& getDamageMax() const { return this->getDamageMax; }
inline const int& getDefense() const { return this->getDefense; }
These are some of the repeating errors.
Error C3867 'Player::getX': non-standard syntax; use '&' to create a pointer to member
Error C2440 'return': cannot convert from 'const double &(__thiscall Player::* )(void) const' to 'const double &'
Error C3867 'Player::getY': non-standard syntax; use '&' to create a pointer to member
Error C2440 'return': cannot convert from 'const double &(__thiscall Player::* )(void) const' to 'const double &'
Error C3867 'Player::getDamageMin': non-standard syntax; use '&' to create a pointer to member
Error C2440 'return': cannot convert from 'const int &(__thiscall Player::* )(void) const' to 'const int &'
Error C3867 'Player::getDamageMax': non-standard syntax; use '&' to create a pointer to member
Error C2440 'return': cannot convert from 'const int &(__thiscall Player::* )(void) const' to 'const int &'
Error C3867 'Player::getDefense': non-standard syntax; use '&' to create a pointer to member
Error C2440 'return': cannot convert from 'const int &(__thiscall Player::* )(void) const' to 'const int &'
Error C3867 'Player::getX': non-standard syntax; use '&' to create a pointer to member
Error C2440 'return': cannot convert from 'const double &(__thiscall Player::* )(void) const' to 'const double &'
Error C3867 'Player::getY': non-standard syntax; use '&' to create a pointer to member

It's hard to be sure because you've written only posted the lines with the errors instead of posting all the relevant code. but it seems you have written code like this
class Player
{
public:
inline const double& getX() const { return this->getX; }
private:
double x;
};
when you should have written code like this
class Player
{
public:
inline const double& getX() const { return this->x; }
private:
double x;
};
Note x not getX.
And then as has already been pointed out in the comments, inline, this and use of references are all redundant or bad in this case. So you can write the even simpler
class Player
{
public:
double getX() const { return x; }
private:
double x;
};

Just explaining the errors in more detail, as the true answer already is given; you are getting two of these for the same issue:
inline const double& getX() const { return this->getX; }
// ^ ^ (!)
Have you noticed that the two identifiers are the same? At the time you are trying to return getX, the function is already declared and known. And you now are trying to return exactly this function.
Error C3867 'Player::getX': non-standard syntax; use '&' to create a pointer to member
With member functions, you can do two things: Either call them or get their address to form a member function pointer. Unlike free-standing functions and static member functions, non-static member functions are not converted automatically to pointers; for these, you need to explicitly specify the address-of operator &:
void f() { }
class C { public: void f() { } };
void (*pf0)() = &f; // explicitly taking address
void (*pf1)() = f; // works for free standing functions
void (C::*pf0)() = &C::f // ONLY can explicitly take address
//void (C::*pf1)() = C::f // gives you the error you saw already
Well, syntax for function pointers, especially member FP, is really uggly. Usually you are better off defining aliases (typedef or using) or, in above case, you could have used auto.
Error C2440 'return': cannot convert from 'const double &(__thiscall Player::* )(void) const' to 'const double &'
Assuming you already fixed the first error (by adding the required &), then you have a type mismatch between what you declared as return type and what you actually are returning; the former a reference to double, the latter a member function pointer. So you can either adjust the return value (impossible in this case: you'd have to return a pointer to a function returning a pointer to a function returning a pointer to ...) or select the correct member as shown already.
If you wonder about __thiscall: It just is the calling convention, which we usually don't have to specify explicitly (unless we need a non-default one – which usually is the case if e. g. coding against WinAPI).

Related

Error: Binding reference of type .. to const

I'm trying to overload operator<<. When trying I got an error saying
Error: Passing const as this argument discards qualifiers
So I added const to my functions but now I'm getting this error:
Binding reference of type .. to const.
Main.cpp
ostream& operator<<(ostream& ostr, const Student& stud){
float mo = 0;
int quantity = stud.get_grade().size();\
.
.
.
Get_grade Function
vector<pair<Subject *, float>>& Student::get_grade() const{
return grade;
}
Error
binding reference of type ‘std::vector<std::pair<Subject*, float> >&’ to ‘const std::vector<std::pair<Subject*, float> >’ discards qualifiers
| return grade;
Grade is a vector
get_grade is a const member function meaning that the type of this pointer inside it is const Student* which in turn means that the data member grade is treated as if it were itself const. But the problem is that the return type of your function is an lvalue reference to non-const std::vector meaning it cannot be bound to a const std::vector.
To solve this just add a low-level const in the return type of the function as shown below:
vvvvv------------------------------------------------------------->low-level const added
const vector<pair<Subject *, float>>& Student::get_grade() const{
return grade;
}

Pointer to a class method call

I am trying to define a class named RationalNumber. In the constructor I want to simplify the fraction represented by the RationalNumber using a callback function to another function (named simplification), but I receive some errors and I can't figure out what I am missing.
The first error is cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
#pragma once
#include <iostream>
using namespace std;
class RationalNumber {
typedef void (RationalNumber::*pointer_to_f)(RationalNumber&);
private:
int a;
int b;
void callback(pointer_to_f);
static int gcd(int, int);
public:
RationalNumber(int = 0, int = 0);
static void simplification(RationalNumber&);
};
RationalNumber::RationalNumber(int x, int y) {
this->a = x;
this->b = y;
pointer_to_f p = &simplification; // <-- line 21, location of the first error
callback((p)(this));
}
int RationalNumber::gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
void RationalNumber::simplification(RationalNumber& x) {
int d = gcd(x.a, x.b);
if (d != 1) {
x.a /= d;
x.b /= d;
}
}
void RationalNumber::callback(pointer_to_f *p(RationalNumber& x) ) {
(*p)(x);
}
The full error log:
Error C2440 'initializing': cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
Error C2511 'void RationalNumber::callback(RationalNumber::pointer_to_f *(__cdecl *)(RationalNumber &))': overloaded member function not found in 'RationalNumber' Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 39
Error C2065 'x': undeclared identifier Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 40
Error (active) E0144 a value of type "void (*)(RationalNumber &x)" cannot be used to initialize an entity of type "RationalNumber::pointer_to_f" Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 21
Error (active) E0147 declaration is incompatible with "void RationalNumber::callback(RationalNumber::pointer_to_f)" (declared at line 11 of "...\source\repos\Prob2\Prob2\NumarRational.h") Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 39
Error (active) E0109 expression preceding parentheses of apparent call must have (pointer-to-) function type Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 22
Error (active) E0020 identifier "x" is undefined Prob2 ...\source\repos\Prob2\Prob2\NumarRational.h 40
Error C2064 term does not evaluate to a function taking 1 arguments Prob2 ....source\repos\Prob2\Prob2\NumarRational.h 22
Thank you!
cannot convert from 'void (__cdecl *)(RationalNumber &)' to 'RationalNumber::pointer_to_f'
on the line
pointer_to_f p = &simplification;
Let's see what we have here. This line initializes a variable (p) of type RationalNumber::pointer_to_f, which corresponds with what the attempted conversion is to. On the right-hand side of the = is the address of RationalNumber::simplification, a static member function from RationalNumber& to void. Check, that matches the error message.
So the first error comes down to the fact that a pointer to member function must point to a non-static member function. The address of a static member function is a normal function pointer (largely because it lacks the hidden this parameter).
Given your setup, it seems to make sense to remove the static keyword from simplification as well as removing its parameter. Have it operate on *this, which becomes available once the member function is no longer static.
Alternatively, you could change your pointers to member functions into regular pointers to functions, if for some reason simplification needs to be static. (Given that the function needs a RationalNumber object in either case, I don't see why static would be desirable.)
The remaining errors are technically independent, but I'll throw in some that have to do with invalid use of a pointer to member function.
callback((p)(this));
This invokes the function pointed to by p and supplies the pointer this as an argument. The returned value (void) becomes the argument to callback. If you want to pass p as the argument to callback, then pass p:
callback(p);
void RationalNumber::callback(pointer_to_f *p(RationalNumber& x) )
This does not match the declaration. You declared callback as a function whose parameter is a pointer_to_f. This definition has a parameter whose type is a function taking a RationalNumber& parameter and returning a pointer_to_f (the x is meaningless here). Be consistent!
void RationalNumber::callback(pointer_to_f p)
If you want to pass in something to use as the argument when p is invoked, you would need a second parameter. See also Function pointer to member function for how to fix the syntax you use to invoke p.
Final note: using a callback here looks like serious over-engineering, but I suppose the need for it might exist in details removed to make the example code simple.
The bellow modified code compiles and shows how to use a static method as a "callback" but as stated above it si not clear why you do not want to directly use simplification method from the constructor (instead of using a pointer of this method)
#include <functional>
class RationalNumber {
private:
int a;
int b;
static int gcd(int, int);
public:
RationalNumber(int = 0, int = 0);
static void simplification(RationalNumber&);
};
RationalNumber::RationalNumber(int x, int y) {
this->a = x;
this->b = y;
std::function<void(RationalNumber&)> p= &RationalNumber::simplification;
p(*this) ;
}
int RationalNumber::gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
void RationalNumber::simplification(RationalNumber& x) {
int d = gcd(x.a, x.b);
if (d != 1) {
x.a /= d;
x.b /= d;
}
}
Function pointers need to be static (cannot be object methods).
So in the above sample you could declare gcd and simplification as standard function (not object methods).

How to overload getter functions without adding/ removing `const`ness of mem function?

I could not figure this out, why C++ is not allowing overloading according to the return type as in the following case
the three member(getter) function has different function signature and even when to store
the pointer to the member function we need different mem-function pointer types like:
for instance T = std::string
using constRefPtr = const std::string&(MyStruct::*)() const;
using constValuePtr = const std::string(MyStruct::*)() const;
using valuePtr = std::string(MyStruct::*)() const;
I have read this similar post, where it was suggestion to have const and non-cost
member functions.
Question: How could I make the following (getter)overloads work without removing constness
of each member functions(if it is possible through standard C++)?
I am using C++17.
#include <iostream>
#include <string>
template<typename T> class MyStruct
{
T m_val;
public:
explicit MyStruct(const T& value)
: m_val(value)
{}
const T& getVal() const { return m_val; } // get val as const ref(no copy of member)
const T getVal() const { return m_val; } // get a const member as return
T getVal() const { return m_val; } // get a copy of member
};
int main()
{
MyStruct<std::string> obj{"string"};
const auto& val_const_ref = obj.getVal(); // overload const std::string& getVal() const
const auto val_const = obj.getVal(); // overload const std::string getVal() const
auto val = obj.getVal(); // overload std::string getVal() const
return 0;
}
error messages I have got:
error C2373 : 'MyStruct<T>::getVal' : redefinition; different type modifiers
note: see declaration of 'MyStruct<T>::getVal'
note: see reference to class template instantiation 'MyStruct<T>' being compiled
error C2059 : syntax error : 'return'
error C2238 : unexpected token(s) preceding ';'
error C2143 : syntax error : missing ';' before '}'
error C2556 : 'const T MyStruct<T>::getVal(void) const' : overloaded function differs only by return type from 'const T &MyStruct<T>::getVal(void) const'
1 > with
1 > [
1 > T = std::string
1 > ]
1 > C:\Z Drive\CPP Programs\Visual Studio Project\Main.cc(62) : note: see declaration of 'MyStruct<std::string>::getVal'
note: see reference to class template instantiation 'MyStruct<std::string>' being compiled
error C2373 : 'MyStruct<std::string>::getVal' : redefinition; different type modifiers
note: see declaration of 'MyStruct<std::string>::getVal'
error C2059 : syntax error : 'return'
error C2238 : unexpected token(s) preceding ';'
error C2146 : syntax error : missing ';' before identifier 'T'
error C2530 : 'val_const_ref' : references must be initialized
error C2789 : 'val_const' : an object of const - qualified type must be initialized
note: see declaration of 'val_const'
You just... can't overload on return type, full stop.
You could just make two differently named functions:
T const& ref() const { return m_val; }
T val() const { return m_val; }
Which themselves could be overloaded based on constness or &ness:
T const& ref() const { return m_val; }
T& ref() { return m_val; }
T val() const& { return m_val; }
T val() && { return std::move(m_val); }
It is not possible. You cannot overload on return type. Overload resolution takes into account the function signature. A function signature is made up of:
function name
cv-qualifiers
parameter types
The standard says:
1.3.11 signature
the information about a function that participates in overload
resolution (13.3): its parameter-type-list (8.3.5) and, if the
function is a class member, the cv-qualifiers (if any) on the function
itself and the class in which the member function is declared. [...]
(Lightly edited from Luchian Grigore's answer)
Question: How could I make the following (getter)overloads work without removing constness of each member functions(if it is possible through standard C++)?
Name them appropriately. And as #Slava points out, when return a copied value there no point in distinguishing between T and const T, so something like:
const T& getConstRefVal() const { return m_val; } // get val as const ref(no copy of member)
T getVal() const { return m_val; } // get a copy of member

error C2664: 'func' : cannot convert parameter 1 from 'int *' to 'const int *&' Conversion loses qualifiers [duplicate]

I ran into an interesting problem while debugging SWIG typemaps today. Anyone care to enlighten me why Visual C++ 2008 throws a "conversion loses qualifiers" error when converting from ourLib::Char * to const ourLib::Char * &? I thought Type * -> const Type * was a trivial conversion, and (when calling functions) Lvalue -> Lvalue & as well.
EDIT: The solution we ended up going with:
// ourLib::Char is a typedef'ed char on Win32
%typemap(in) const char* (const ourLib::Char* tmp)
{
if (!bapiLua::LuaTraits<ourLib::Char*>::FromLuaObject(L, $argnum, tmp)) SWIG_fail;
$1 = const_cast<char *>(tmp);
}
// And in a different source file, already written:
namespace bapiLua {
template<>
struct LuaTraits<ourLib::Char*>
{
static ourLib::Bool FromLuaObject(lua_State* L, int pos, const ourLib::Char*& o_result);
};
}
Removing the const from const ourLib::Char * tmp causes the error I described.
Say you had the following function:
void test( const char*& pRef)
{
static const char somedata[] = { 'a' ,'b', 'c', '\0'};
pRef = somedata;
}
If you passed in a non-const char*, then when test() returned the compiler would have lost the fact that what p is pointing to is const.
It's essentially the same reason as given in this C++ FAQ Lite question (dealing with pointers-to-pointers rather than pointer references):
http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17
In following code,
friend ostream & operator<<(ostream & output, const List& other)
{
for(int i=0;i<other.length();i++)
output << other.getData()[i] << " ";
return output;
}
to remove compilation error "Conversion loses qualifiers", for parameter "const List& other", I changed both following called methods to const.
T* getData() const
{
return data;
}
int length() const
{
return lSize;
}

const at the end of one method giving error

I don't understand why I get error with che const at the end of my method. The method print doesn't change any class member, right?
class Hello{
public:
int get_member() {return member_;};
void print() const {
cout<<get_member()<<endl;
};
private:
int member_;
};
The error message is:
error passing "const Hello" as "this" argument of 'int Hello:: get_member()' discards qualifiers [-fpermissive]
int get_member() const {return member_;}
Should fix it. You can't call a non-const member from a const member as it breaks the 'promise' of const. If you could there would be no guarantee that the object isn't modified during the call.