Gentlepeople,
I do not understand the interaction between templates and const
member functions(and arguments) as shown in the simplified example
program below.
Any help with explaining why this happens is much appreciated.
thanks,
-sr
//____________________________________________________________
template<int size>
class A {
public:
A() {};
virtual ~A() {};
int GetSize(void) { return size; }
};
class B : public A<1> {
public:
B(): A<1>() {}
virtual ~B() {}
// Implementation A: This compiles fine.
bool operator==(B& rhs) {
return (GetSize()==rhs.GetSize());
}
// Implementation B: This gives compile errors
bool operator==(const B& rhs) const {
return (GetSize()==rhs.GetSize());
}
/*
* ______________________________________________________________
* g++ test_const.cpp
* test_const.cpp: In member function `bool B::operator==(const B&)
* const':
* test_const.cpp:21: passing `const B' as `this' argument of `int
* A<size>::GetSize() [with int size = 1]' discards qualifiers
* test_const.cpp:21: passing `const B' as `this' argument of `int
* A<size>::GetSize() [with int size = 1]' discards qualifiers
*
* ______________________________________________________________
* cl /EHsc test_const.cpp
* Microsoft (R) 32-bit C/C++ Optimizing Compiler
* Version 14.00.40607.16 for 80x86
*
* test_const.cpp
* test_const.cpp(21) : error C2662: 'A<size>::GetSize' :
* cannot convert 'this' pointer from 'const B' to 'A<size> &'
* with
* [
* size=1
* ]
* Conversion loses qualifiers
* test_const.cpp(21) : error C2662: 'A<size>::GetSize' :
* cannot convert 'this' pointer from 'const B' to 'A<size> &'
* with
* [
* size=1
* ]
* Conversion loses qualifiers
* ______________________________________________________________
*
* The errors only occur with a base class access. I am however
* unsure as to why. Would appreciate any help with gaining an
* understanding. -sr
*/
};
int main(void) { return 0;}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
srgama (1)
|
4/18/2005 3:11:43 PM |
|
srgama@gmail.com wrote:
> Gentlepeople,
> I do not understand the interaction between templates and const
> member functions(and arguments) as shown in the simplified example
> program below.
>
> Any help with explaining why this happens is much appreciated.
>
> thanks,
> -sr
>
> //____________________________________________________________
> template<int size>
> class A {
> public:
> A() {};
> virtual ~A() {};
> int GetSize(void) { return size; }
> };
>
> class B : public A<1> {
> public:
> B(): A<1>() {}
> virtual ~B() {}
>
> // Implementation A: This compiles fine.
> bool operator==(B& rhs) {
> return (GetSize()==rhs.GetSize());
> }
>
> // Implementation B: This gives compile errors
> bool operator==(const B& rhs) const {
> return (GetSize()==rhs.GetSize());
Since this expression requires a call to the base class, and that would
require converting 'this' to 'A*' and 'rhs' to 'A&', and since such
conversions while exist, do not cast away constness, both 'this' and
'rhs' get converted to 'A const*' and 'A const&', respectively. After
that the attempt to call a function that is non-const (GetSize() is not
declared 'const') fails.
This has nothing to do with templates. Just declare your A::GetSise()
function 'const':
class A {
...
int GetSize() const { return size; }
and everything is going to be fine.
> } [...]
V
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Victor
|
4/19/2005 10:00:09 PM
|
|
srgama@gmail.com wrote:
> I do not understand the interaction between templates and const
> member functions(and arguments) as shown in the simplified example
> program below.
Good job simplifying your program. You gave just enough detail to
show the problem without posting your entire project.
The problem is "const correctness," not templates. I have
converted class A into a simple class to make the real problem
more clear.
> class A {
> public:
> A() {};
> virtual ~A() {};
> int GetSize(void) { return 1; }
/**
Note that GetSize is a *NON-const* function. You cannot call it
on a const object. (It could be const -- it doesn't modify
anything -- but it isn't declared as const.)
A a1;
const A a2;
std::cout << a1.GetSize(); // OK
std::cout << a2.GetSize(); // Error: GetSize() isn't const!
**/
> };
>
> class B : public A {
> public:
> B(): A() {}
> virtual ~B() {}
>
> // Implementation A: This compiles fine.
> bool operator==(B& rhs) {
> return (GetSize()==rhs.GetSize());
> }
/**
Note that this version is a *NON-const* function. That's okay;
nothing you're doing inside the function requires const. You
can't call this on a const B object, though.
**/
> // Implementation B: This gives compile errors
> bool operator==(const B& rhs) const {
> return (GetSize()==rhs.GetSize());
> }
/**
This version is a *CONST* function. You CAN call it on a const
B object. But you're trying to call GetSize(). As far as the
compiler knows, GetSize() alters the A sub-object -- you can't
do that in a const function.
**/
> };
So the solution is to make GetSize() into a const function:
//______________________________________________________________
template<int size> class A {
public:
A() {};
virtual ~A() {};
int GetSize(void) const { return size; }
};
class B : public A<1> {
public:
B(): A<1>() {}
virtual ~B() {}
bool operator==(const B& rhs) const {
return (GetSize()==rhs.GetSize()); // Okay now
}
};
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Allan
|
4/19/2005 10:12:49 PM
|
|
Hello
srgama@gmail.com wrote:
> I do not understand the interaction between templates and const
> member functions(and arguments) as shown in the simplified example
> program below.
There is none. BTW there is no const member function either.
> Any help with explaining why this happens is much appreciated.
> int GetSize(void) { return size; }
because this should be "int GetSize(void) const { return size; }".
It has nothing to do with templates. You simply attempted to call a
non-const member function through a const reference.
Markus
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Markus
|
4/19/2005 10:27:38 PM
|
|
srgama@gmail.com wrote:
> I do not understand the interaction between templates and const
> member functions(and arguments) as shown in the simplified example
> program below.
>
> Any help with explaining why this happens is much appreciated.
>
[code snipped]
>
That's why:
http://www.parashift.com/c++-faq-lite/const-correctness.html
--
Ahti Legonkov
leg zero at hot dot ee
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ahti
|
4/19/2005 10:30:02 PM
|
|
In article <1113834146.980598.43460@l41g2000cwc.googlegroups.com>,
srgama@gmail.com wrote:
> Gentlepeople,
> I do not understand the interaction between templates and const
> member functions(and arguments) as shown in the simplified example
> program below.
>
> Any help with explaining why this happens is much appreciated.
Templates and inheritance are orthogonal to the issue of const member
functions. Here is a real simplified example:
class C
{
public:
int GetSize() { return 0; }
// Does not compile
bool operator==(const C& rhs) const
{
return GetSize() == rhs.GetSize();
}
};
Basically, the issue is that const member functions treat all
(non-mutable non-static) member variables as const, and can only call
(static or) const member functions.
operator==(), being a const member function, cannot call GetSize(),
which is a non-const member function.
Regards,
Nevin ":-)" Liber
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Nevin
|
4/19/2005 10:31:12 PM
|
|
Hello "srgama",
srgama@gmail.com schrieb:
>Gentlepeople,
>I do not understand the interaction between templates and const
>member functions(and arguments) as shown in the simplified example
>program below.
>
Your problem is not related to templates, see below.
>//____________________________________________________________
>template<int size>
>class A {
>public:
>A() {};
>virtual ~A() {};
>int GetSize(void) { return size; }
This is a non-const member function. It means that
A<SomeType> a; // Note: a is mutable!
a.GetSize();
is a valid while
A<SomeType> const a; // Note: a is **immutable**!
a.GetSize();
is **not**.
You could simplify things by removing templatability and compare
class A2 {
public:
A2() {};
virtual ~A2() {};
int GetSize(void) { return 0; }
}
Here we have
A2 a; // Note: a is mutable!
a.GetSize(); // OK
A2 const a2; // Note: a2 is **immutable**!
a.GetSize(); // ERROR
>};
>
>class B : public A<1> {
>public:
>B(): A<1>() {}
>virtual ~B() {}
>
>// Implementation A: This compiles fine.
>bool operator==(B& rhs) {
> return (GetSize()==rhs.GetSize());
>}
It compiles fine, because
- operator== is a **mutable** member function
- Its argument is B& and thus a **mutable** object
So you are allowed to call the mutable GetSize() function on *this and
on rhs.
>// Implementation B: This gives compile errors
>bool operator==(const B& rhs) const {
> return (GetSize()==rhs.GetSize());
>}
It does not (and should not) compile, because
- operator== is an **immutable** member function (as it should be!)
- Its argument is const B& and thus an **immutable** object (as it
should be!)
- but you try to call a mutable member function (namely GetSize) for
*this and
rhs, which are both immutable objects.
This teaches us: Take care of const-correctness!
Since GetSize() obviously is a "read-only" member function and does not
change the internal state of A or B, the correct declaration would be:
bool GetSize() const;
instead of
bool GetSize();
Greetings from Bremen,
Daniel Kr�gler
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
ISO
|
4/20/2005 6:10:08 AM
|
|
srgama@gmail.com wrote in message news:<1113834146.980598.43460@l41g2000cwc.googlegroups.com>...
> Gentlepeople,
> I do not understand the interaction between templates and const
> member functions(and arguments) as shown in the simplified example
> program below.
>
> Any help with explaining why this happens is much appreciated.
>
> thanks,
> -sr
>
> //____________________________________________________________
> template<int size>
> class A {
> public:
> A() {};
> virtual ~A() {};
> int GetSize(void) { return size; }
> };
>
> class B : public A<1> {
> public:
> B(): A<1>() {}
> virtual ~B() {}
>
> // Implementation A: This compiles fine.
> bool operator==(B& rhs) {
> return (GetSize()==rhs.GetSize());
> }
>
> // Implementation B: This gives compile errors
> bool operator==(const B& rhs) const {
> return (GetSize()==rhs.GetSize());
> }
> /*
> * ______________________________________________________________
> * g++ test_const.cpp
> * test_const.cpp: In member function `bool B::operator==(const B&)
> * const':
> * test_const.cpp:21: passing `const B' as `this' argument of `int
> * A<size>::GetSize() [with int size = 1]' discards qualifiers
> * test_const.cpp:21: passing `const B' as `this' argument of `int
> * A<size>::GetSize() [with int size = 1]' discards qualifiers
> *
> * ______________________________________________________________
> * cl /EHsc test_const.cpp
> * Microsoft (R) 32-bit C/C++ Optimizing Compiler
> * Version 14.00.40607.16 for 80x86
> *
> * test_const.cpp
> * test_const.cpp(21) : error C2662: 'A<size>::GetSize' :
> * cannot convert 'this' pointer from 'const B' to 'A<size> &'
> * with
> * [
> * size=1
> * ]
> * Conversion loses qualifiers
> * test_const.cpp(21) : error C2662: 'A<size>::GetSize' :
> * cannot convert 'this' pointer from 'const B' to 'A<size> &'
> * with
> * [
> * size=1
> * ]
> * Conversion loses qualifiers
> * ______________________________________________________________
> *
> * The errors only occur with a base class access. I am however
> * unsure as to why. Would appreciate any help with gaining an
> * understanding. -sr
> */
> };
>
> int main(void) { return 0;}
The GetSize() function declared in the base class is not a const
member function. It is an error to call a non-const member function
from a const member function even in the absence of templates. If you
change the declaration of the A to the following: -
template<int size>
class A {
public:
A() {};
virtual ~A() {};
int GetSize(void) const { return size; }
};
Both Implementation A and Implementation B should compile.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
junker98
|
4/20/2005 9:07:02 AM
|
|
srgama@gmail.com wrote:
> Gentlepeople,
> I do not understand the interaction between templates and const
> member functions(and arguments) as shown in the simplified example
> program below.
>
> Any help with explaining why this happens is much appreciated.
It doesn't look like an interaction at all to me, it just looks like
you're calling a non-const method on a const object.
>
> thanks,
> -sr
>
> //____________________________________________________________
> template<int size>
> class A {
> public:
> A() {};
> virtual ~A() {};
> int GetSize(void) { return size; }
> };
>
> class B : public A<1> {
> public:
> B(): A<1>() {}
> virtual ~B() {}
>
> // Implementation A: This compiles fine.
> bool operator==(B& rhs) {
> return (GetSize()==rhs.GetSize());
> }
OK, so you're calling the non-const A<1>::GetSize() method on two
objects, rhs and *this.
> // Implementation B: This gives compile errors
> bool operator==(const B& rhs) const {
> return (GetSize()==rhs.GetSize());
> }
Now you're calling the same non-const method on two const objects,
which isn't allowed. This isn't usually allowed, though, so why assume
it is because A is a template?
Try const-qualifying A<size>::GetSize, or adding a const overload.
Alternatively, make it static, since it doesn't use any instance data.
If it could be static, of course, it will be the same for all instances
of B, and operator== will always return true. I assume this is an
artefact of the stripped-down example, though?
Simon.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
simont
|
4/20/2005 9:14:01 AM
|
|
It is complaining about GetSize() not being const.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Roger
|
4/20/2005 9:21:16 AM
|
|
srgama@gmail.com wrote:
> Gentlepeople,
> I do not understand the interaction between templates and const
> member functions(and arguments) as shown in the simplified example
> program below.
I don't think templates have anything to do with your problem. It is an
error to call a non const member function from a const member function
of the same class. If you turn your class template A in a non template
class you'll get the same errors.
Cheers,
Nicola Musatti
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Nicola
|
4/20/2005 9:21:59 AM
|
|
To explain further, when you make rhs a const variable, you are making
a promise that you won't modify the object pointed to by that
reference, however you cannot honour that promise because you are
calling GetSize() on rhs, which isn't a const function. Just make
GetSize() const and the error should go away.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Roger
|
4/20/2005 9:22:41 AM
|
|
I believe this has nothing to do with the template aspect of the
problem. The problem is that your A::GetSize method is not defined
const so it can't be called via a const instance of B.
Try this in A instead:
int GetSize(void) const { return size; }
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Peter
|
4/20/2005 9:34:48 AM
|
|
|
12 Replies
302 Views
(page loaded in 0.152 seconds)
Similiar Articles: const member functions in classes derived from templates. - comp ...Gentlepeople, I do not understand the interaction between templates and const member functions(and arguments) as shown in the simplified example progr... Non-member operator overloading, linker complains - comp.lang.c++ ...const member functions in classes derived from templates. - comp ... You simply attempted to call a non-const member ... and can only call (static or) const member ... struct with const member variable without explicit constructor ...const member functions in classes derived from templates. - comp ... struct with const member variable without explicit constructor ... const member functions in classes ... Get rid of unused parameter warning? - comp.lang.c++const member functions in classes derived from templates. - comp ... Get rid of unused parameter warning? - comp.lang.c++ const member functions in classes derived from ... Why can not I implicitly convert "Derived **" to "Base * const ...const member functions in classes derived from templates. - comp ... Why can not I implicitly convert "Derived **" to "Base * const ... const member functions in classes ... Static const integral data members can be initialized? - comp.lang ...const member functions in classes derived from templates. - comp ... Static const integral data members can be initialized? - comp.lang ... const member functions in ... cannot write std::map via ostream_iterator? - comp.lang.c++ ...const member functions in classes derived from templates. - comp ... cannot write std::map via ostream_iterator? - comp.lang.c++ ... const member functions in classes ... Making use of run-time dynamic linking (Examples?) - comp.lang.c++ ...const member functions in classes derived from templates. - comp ... Making use of run-time dynamic linking (Examples?) - comp.lang.c++ ... const member functions in ... nitializing a static vector <> of integers (this static vectorconst member functions in classes derived from templates. - comp ..... template<int size ... of integers (this static ... const member functions in classes derived from ... Expression templates and array indexing - comp.lang.c++.moderated ...const member functions in classes derived from templates. - comp ..... return (GetSize()==rhs.GetSize()); Since this expression ... Templates and inheritance are ... Different const qualifiers warning ....should this be? - comp ...const member functions in classes derived from templates. - comp ..... int size = 1]' discards qualifiers * test_const ... size; } because this should be "int GetSize ... std::map< MyString, MyString > comparison operator? - comp.lang ...const member functions in classes derived from templates. - comp ... std::map MyString, MyString > comparison operator? - comp.lang ... const member functions in classes ... Simple error : method format(String, Object[]) is not applicable ...const member functions in classes derived from templates. - comp ... Simple error : method format(String, Object[]) is not applicable ... const member functions ... member ... between-and operator - comp.soft-sys.sasconst member functions in classes derived from templates. - comp ... Gentlepeople, I do not understand the interaction between templates and const member ... Structural Member - adding more sizes - comp.cad.solidworks ...Structural Member - adding more sizes - comp.cad.solidworks ... ... to add to ... named) file, not a header file, or the member will probably be defined more ... templates ... const member functions in classes derived from templates. - comp ...Gentlepeople, I do not understand the interaction between templates and const member functions(and arguments) as shown in the simplified example progr... Member Functions of Template Classes (C++)Member functions can be defined inside or outside of a class template. They are defined like function ... void MyStack< T, i >::push( const T item ) { }; template< class T ... 7/27/2012 3:50:36 PM
|