top-level const-ness inhibits override

  • Thread starter Thread starter Ben Voigt
  • Start date Start date
B

Ben Voigt

Found another variation on my previous bug
(https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100917)
I would welcome validation and votes.




class ISkewEstimator

{

virtual void get_Sum(double* const pdRetval) const = 0;

};

class CSkewEstimator : public ISkewEstimator

{

virtual void get_Sum(double* pdRetval) const override; // remove explicit
override for other compilers

};

CSkewEstimator skewInstance;







1>overrideconstness.cpp

1>c:\programming\constness\overrideconstness.cpp(8) : warning C4301:
'CSkewEstimator::get_Sum': overriding virtual function only differs from
'ISkewEstimator::get_Sum' by const/volatile qualifier

1> c:\programming\constness\overrideconstness.cpp(3) : see declaration of
'ISkewEstimator::get_Sum'

1>c:\programming\constness\overrideconstness.cpp(8) : error C3668:
'CSkewEstimator::get_Sum' : method with override specifier 'override' did
not override any base class methods

1>c:\programming\constness\overrideconstness.cpp(11) : error C2259:
'CSkewEstimator' : cannot instantiate abstract class

1> due to following members:

1> 'void ISkewEstimator::get_Sum(double *const ) const' : is abstract

1> c:\programming\constness\overrideconstness.cpp(3) : see declaration of
'ISkewEstimator::get_Sum'
 
Ben Voigt said:
I'd also appreciate it if someone with VC2003 could test (take off the
explicit override keyword) and see if it is a regression, I believe that
it worked ok there.

I used VS2003 to compile it.

test.cpp(10) : warning C4301: 'CSkewEstimator::get_Sum': overriding virtual
function only differs from 'ISkewEstimator::get_Sum' by const/volatile
qualifier

test.cpp(5) : see declaration of 'ISkewEstimator::get_Sum'

test.cpp(14) : error C2259: 'CSkewEstimator' : cannot instantiate abstract
class

due to following members:

'void ISkewEstimator::get_Sum(double *const ) const' : pure virtual function
was not defined

test.cpp(5) : see declaration of 'ISkewEstimator::get
 
int main()

{

class ISkewEstimator

{

virtual void get_Sum(double* const pdRetval)const = 0;

};

class CSkewEstimator : public ISkewEstimator

{

virtual void get_Sum(double* const pdRetval)const override{};

};

CSkewEstimator skewInstance;

return 0;

};

This compiles with VC2005.
 
eddie geer said:
int main()

{

class ISkewEstimator

{

virtual void get_Sum(double* const pdRetval)const = 0;

};

class CSkewEstimator : public ISkewEstimator

{

virtual void get_Sum(double* const pdRetval)const override{};

};

CSkewEstimator skewInstance;

return 0;

};

This compiles with VC2005.

You added const, where it is not necessary according to the C++ standard.
What if the implementation CSkewEstimator::get_Sum actually did modify its
local copy of the pointer? You would have to change the interface
declaration because of an implementation detail. What if some
implementations of get_Sum treat the argument as const and some do not (not
referring to the pointed-to location, which is non-const, but the pointer
itself)? Then you would have to sacrifice const-correctness in order to
compile.

I shouldn't have to modify standards-compliant code that is developed with
gcc, to have VC++ compile it. I presented a minimal example, there are many
more member functions and several classes are affected.
 
Ben said:
You added const, where it is not necessary according to the C++ standard.

I agree, you should be able to create a const interface for that
non-const argument.

I have validated your bug, I'm getting the same errors on my VS2003 and
VS2005 SP1.

http://www.comeaucomputing.com/tryitout/ liked your code and compiled it
without errors. Interestingly, your code works on Borland C++Builder 6,
which gets quite a lot of complaints for its non-standards compliance.

On http://dinkumware.com/exam/, only MINGW compiled it successfully.

Tom
 
Here's a workaround, but it's very painful if it affects a lot of
functions, and it's a performance hit as well, since you need to call
yet another virtual function:

class CSkewEstimator : public ISkewEstimator
{

virtual void get_Sum(double* const pdRetval) const override
{ get_SumNonCost(pdRetval); }
virtual void get_SumNonCost(double* pdRetval) const { }

};
 
Tamas Demjen said:
Here's a workaround, but it's very painful if it affects a lot of
functions, and it's a performance hit as well, since you need to call yet
another virtual function:

Actually, the shim needs to be virtual, but the implementation doesn't.

I had less than two dozen functions total, and my interfaces were for
decoupling rather than polymorphism, so I had already made the interface
match exactly, but I wanted to get the bug validated because rejecting
compliant code obviously isn't pretty.
 
Ben said:
I wanted to get the bug validated because rejecting
compliant code obviously isn't pretty.

If you need more confirmation, I have the standard draft in front of me,
date: 2005-10-19, page 247, 13.1 Overloading:

"Parameter declarations that differ only in the presence or absence of
const and/or volatile are equivalent. That is, the const and volatile
type-specifiers for each parameter type are ignored when determining
which function is being declared, defined, or called."

"Only the const and volatile type-specifiers at the outermost level of
the parameter type specification are ignored in this fashion"

So "double* pdRetval" is equivalent to "double* const pdRetval" from the
overload's point of view.

Obviously "double*" is not equivalent to "const double*".
 
Tamas said:
I agree, you should be able to create a const interface for that
non-const argument.

I have validated your bug, I'm getting the same errors on my VS2003 and
VS2005 SP1.

http://www.comeaucomputing.com/tryitout/ liked your code and compiled it
without errors. Interestingly, your code works on Borland C++Builder 6,
which gets quite a lot of complaints for its non-standards compliance.

On http://dinkumware.com/exam/, only MINGW compiled it successfully.

Tom

Interesting - I wonder if the Dinkumware exam site uses any of the
compatibility switches for the EDG front end (or perhaps uses the
default switches on Windows, which will enable MS compatibility mode),
since I'd be quite surprised if EDG had this bug in their ISO compliant
mode. Also, Comeau C++ compiles it fine.

Tom
 
Back
Top