While writing the following function abs, I get the error:
non-member function unsigned int abs(const T&) cannot have cv-qualifier.
template<typename T>
inline unsigned int abs(const T& t) const
{
return t>0?t:-t;
}
After removing the const qualifier for the function there is no error. Since I am not modifying t inside the function the above code should have compiled. I am wondering why I got the error?
Your desire not to modify t is expressed in const T& t. The ending const specifies that you will not modify any member variable of the class abs belongs to.
Since there is no class where this function belongs to, you get an error.
The const modifier at the end of the function declaration applies to the hidden this parameter for member functions.
As this is a free function, there is no this and that modifier is not needed.
The t parameter already has its own const in the parameter list.
The cv-qualifier on a member function specifies that the this pointer is to have indirected type const (or volatile, const volatile) and that therefore the member function can be called on instances with that qualification.
Free functions (and class static functions) don't have a this pointer.
As we all know, const keyword followed after the argument list indicates that this is a pointer to a pointer constant.
There is a non-member function, it does not belong to the class, so add const opposite end error occurs.
Solution to the problem: is to either become a class member function or remove the const keyword const opposite end
Related
Can I have two overloaded operator[] like this in the same class?
I am confused which definition is used when I use operator[], isn't int ambiguous? Don't they have the same signature?
template <class T, int n>
class ArrayTP
{
private:
T ar[n];
public:
ArrayTP() {};
virtual T & operator[](int i);
virtual T operator[](int i) const;
};
This class contains declarations of these overloaded operator. I have not included definition in my question, though.
Overloaded operators works no different than normal overloaded functions. It's just they are special function. So I'm giving you general example from function same applies to any kind of functions.
As you must know that, top-level const has no effect on the
objects that can be passed to the function. A parameter that has a top-level const is
indistinguishable from one without a top-level const:
Record lookup(Phone);
Record lookup(const Phone); // redeclares Record lookup(Phone)
Record lookup(Phone*);
Record lookup(Phone* const); // redeclares Record lookup(Phone*)
In these declarations, the second declaration declares the same function as the first.
On the other hand, we can overload based on whether the parameter is a reference
(or pointer) to the const or nonconst version of a given type; such consts are
low-level.
// functions taking const and nonconst references or pointers have different parameters
// declarations for four independent, overloaded functions
Record lookup(Account&); // function that takes a reference to Account
Record lookup(const Account&); // new function that takes a constbreference.
Record lookup(Account*); // new function, takes a pointer to Account
Record lookup(const Account*); // new function, takes a pointer to const
In these cases, the compiler can use the constness of the argument to distinguish
which function to call. Because there is no conversion from const,
we can pass a const object (or a pointer to const) only to the version with a
const parameter. Because there is a conversion to const, we can call either
function on a nonconst object or a pointer to nonconst. However, the compiler will prefer the nonconst versions when we pass a
nonconst object or pointer to nonconst.
Examples from primer.
I have seen a code portion in the boost example which is used to construct a state machine. What confused me is the two member functions ElapsedTime()? Is this allowed for the two functions to have the same signatures such as function name and parameters type?
I have googled a lot but without any luck to find relevant info about this. Any advice on this would be greatly appreciated.
struct Active : sc::simple_state< Active, StopWatch, Stopped >
{
public:
typedef sc::transition< EvReset, Active > reactions;
Active() : elapsedTime_( 0.0 ) {}
double ElapsedTime() const { return elapsedTime_; }
double & ElapsedTime() { return elapsedTime_; }
private:
double elapsedTime_;
};
Signature of a function is defined by the name and by the argument types.
You have two functions with the same name, but they do not get the same arguments!
You might wonder how could it be?
So, each member function gets another parameter implicitly: this is the "this" pointer. A pointer to the object who called that method.
When you add const in the end of the method, you specify the "this" argument as a const pointer to const. In the other method (without the const), the type of "this" is just const pointer.
Hence, you have two methods with different signature, and there is no problem at all.
They do not have the same signatures - one is const and another one is not. Constness is part of member function signature.
The signatures are different because one has const qualifier.
http://www.cprogramming.com/tutorial/const_correctness.html
Is this allowed
This usage is allowed as over.load#2.2 states:
Member function declarations with the same name and the same parameter-type-list cannot be overloaded if any of them is a static member function declaration ([class.static]). Likewise, member function template declarations with the same name, the same parameter-type-list, and the same template parameter lists cannot be overloaded if any of them is a static member function template declaration. The types of the implicit object parameters constructed for the member functions for the purpose of overload resolution ([over.match.funcs]) are not considered when comparing parameter-type-lists for enforcement of this rule. In contrast, if there is no static member function declaration among a set of member function declarations with the same name and the same parameter-type-list, then these member function declarations can be overloaded if they differ in the type of their implicit object parameter. [ Example: The following illustrates this distinction:
(end quote)
Now, in your example the first overload has a const qualifer which means that its implicit object parameter has type const Active& while the second overload has no const qualifer meaning that its implicit object parameter is of type Active&. Moroever, there is no static member function declaration for ElapsedTime with the same paremeer-type-list. Hence using the above quoted statement, this means that the given usage is allowed.
Note
Note that the currently accepted answer is technically incorrect because it claims that this is a const pointer to const. But in reality the standard specifies that inside a const qualified member function the this pointer is of type const X* while inside a non-const qualified member function the this pointer is of type X*.
I'm currently working on material from my data structures class, which involves an exercise where we attempt to define a class mimicking a vector so we can get an understanding of what's going on underneath the hood. Everything made sense until I realized that there are two definitions foroperator[]. In context:
typedef unsigned int size_type;
T& operator[] (size_type i) { return m_data[i]; }
const T& operator[] (size_type i) const { return m_data[i]; }
First question: why is it necessary to have two definitions of operator[]?
Second question: why doesn't this throw a multiple definitions error?
Sorry if anything is vague or seems obvious. I'm new to C++, my only other experience being in Java. Thanks!
This is a common C++ pattern.
The const member function (that is, the one with the keyword const after the prototype) applies when *this is const; in other words, if it is used with a const object. Since *this is const, it's reasonable to assume that it cannot be modified, so operator[] must return a const reference.
The other member function would apply to any object, but since it is less specific than the const one, it only applies if *this is not const. In that case, it is presumably possible to modify the returned reference (object[3] = new_value;), so the return type is not const.
First question: why is it necessary to have two definitions of
operator[]?
Those definitions differ with their const-qualifier (and result type). One of them is const and returns const reference to internal data. It is used if your container is declaread as const, so that reference to it's contents are const as well. If your contianer is not const, non-const operator is used so that internal data can be modified.
Second question: why doesn't this throw a multiple definitions error?
Because const-qualifier is a part of function prototype, which means that void foo(); and void foo() const; are actually two diffrent methods. It allows overloading based on const qualifier of object being used to call the method.
why is it necessary to have two definitions of operator[]?
It's necessary if you want one that you can modify its value (e.g. obj[i] = value) and the other cannot (with const).
why doesn't this throw a multiple definitions error?
Based on $9.3.1/3 states-
"A nonstatic member function may be declared const, volatile, or const volatile. These cvqualifiers affect the type of the this pointer (9.3.2). They also affect the function type (8.3.5) of the member function; a member function declared const is a const member function, a member function declared volatile is a volatile member function and a member function declared const volatile is a const volatile member function."
That said, you can overload a function by using one of those qualifiers, e.g.:
void func();
void func() const;
Each function can be recognized by what you can call signature, when you declare a function in C++ you write the signature of the function, a signature looks like
qualifiers T ( qualifiers U u ) qualifiers;
############ ------------------ ::::::::::
so the signature it's composed of the 2 part that I outlined with # and -, the part with # is the return type and the part - is the description for the arguments accepted by the function.
The point is that if you write the same signature with different qualifiers, C++ still considers this the re-declaration/re-definition of the same function, so qualifiers are part of the signature but when comparing multiple declarations/definitions of functions with the same name they are virtually dropped by your compiler.
You should read more about qualifiers, I simplified the concept here.
You can also add more qualifiers after the signature, the part I outlined with :, to declare some properties about the way your function works, for example const means that you declare that your function doesn't modify the variables that it can access .
What is the reason why pointers to member functions, can't point to const member functions?
struct A {
void g() {};
void f() const {}
};
Later in code:
void (A::* fun)() = &A::f;
This code produces:
error: cannot convert ‘void (A::*)()const’ to ‘void (A::*)()’ in initialization
Of course it compiles with &A::g instead of &A::f.
In opposite situation:
void (A::* fun)() const = &A::g;
The error is:
error: cannot convert ‘void (A::*)()’ to ‘void (A::*)()const’ in initialization
The second case is rather clear. const pointer isn't expected to modify the object so it can't hold the function which does it. But why it's not possible to assign const member function to non-const member function as in the first case?
It looks like the rule for normal pointers where casting const to non-const would allow to modify the value, but I don't see the point here, where const-correctness is checked in function definition, before such assignment.
What is the reason why pointers to member functions, can't point to const member functions?
Because the const modifier is part of the function signature. Once you declare a function pointer, that function pointer can only be used to assign pointers to function that have the same function signature.
Non-static member functions have an extra hidden this parameter. Given the existence of that that extra hidden parameter, a non-static void A::f() const; behaves much like void A__f(const A *__this), and the behaviour you see for member functions models the behaviour for non-member functions.
void f(void *);
void (*pf)(const void *) = f; // also an error
As for whether it could break on any implementation, I suppose in theory, an implementation is permitted to read a void * parameter from a different register than a const void * parameter, and if so, the result of the conversion (were it valid) could not be used to call f properly. I have no idea why any implementor would make such a decision, and I don't know of any real implementation that does so, but it's one allowed by the standard.
I overload an operator twice with the same parameter list. but with different return type:
T& operator()(par_list){blablabla}
const T& operator()(par_list){blablabla}
So when I'm calling the () operator, which function would be called based on what preference or situation? I know that if I call () under const function it has to be the const T& one.
I'm just curious how C++ deal with such situation and how the default preference works.
Thanks
These functions don't overload each other; they have the same signatures, and so the attempt to redefine the same function, which is an error. The return type is not part of a function's signature. To overload a function, you must declare a second function with the same name, but different parameters or const/volatile qualifiers - that is, qualifiers on the function, not the return type.
(They don't override each other either; overriding is what derived classes do to their base classes' virtual functions).
It's common to define a const and a non-const overload of a member function; the const overload must declare the function const, not just the return type:
T& operator()(par_list){blablabla}
const T& operator()(par_list) const {blablabla}
^^^^^
Now the first will be called if you apply () to a non-const object, and the second on a const object. For example:
Thingy nc;
Thingy const c;
nc(); // calls the first (non-const) overload
c(); // calls the second (const) overload
You can't overload a function/method based on return type. I would expect the compiler to throw an error here. What you can do is specify the method itself as a const method, using
const T& operator()(par_list) const {blahblah}
The const qualifier not only means this can be called on a const receiver, but it also is used in the overload resolution. This happens because it affects the implicit *this parameter that's passed to the method; a const method uses a const qualifier on *this, and const qualifiers are taken into account during overload resolution.
The way you define your operators, no way the compiler can decide which operator() to call. Overloading of functions (and operators) can only be done on the type of the arguments, never on the return type. And in fact, you will have an error at compilation as soon as you define the second one, the compiler considering that you are redefining the same function/operator.
However, the following is common (and probably what you have):
T& operator()(par_list){blablabla}
const T& operator()(par_list) const {blablabla}
This additional "const" after the argument list exists because you are defining non-static member functions and member functions have an implicit hidden argument: the "this" pointer to the instance of the class. The "const" keyword there indicates if this hidden pointer is to a const instance or not. This argument participates to the overloading resolution and that is in this case what the compiler use to choose which version of the operator to use.
So:
class A {
T& operator()() { ... }
const T& operator()() const { .... }
};
A a;
const A& ca(a);
a(); -> returns a T&
ca(); -> returns a const T&