Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How come a const temporary chooses to call a non-const member function over a const one? [duplicate]

The example code is taken from: http://en.cppreference.com/w/cpp/types/add_cv (I modified a little.)

struct foo
{
    void m() { std::cout << "Non-cv\n"; }
    void m() const { std::cout << "Const\n"; }
};

template<class T>
void call_m()
{
  T().m();
}

int main()
{
    call_m<foo>();
    call_m<const foo>(); //here
}

And the output is:

Non-cv
Non-cv

in the second call, T is const qualified, so T() should call the const version, right? or are there some special rules I missed?

like image 586
Frahm Avatar asked May 22 '13 11:05

Frahm


People also ask

Can a const member function call a non-const function?

Const member functions in C++ It is recommended to use const keyword so that accidental changes to object are avoided. A const member function can be called by any type of object. Non-const functions can be called by non-const objects only.

What will happen if a const object calls a non-const member function?

If the function is non-constant, then the function is allowed to change values of the object on which it is being called. So the compiler doesn't allow to create this chance and prevent you to call a non-constant function on a constant object, as constant object means you cannot change anything of it anymore.

How do you call a non-const method from the const method?

Obviously you can't call a non- const method from a const method. Otherwise, const would have no meaning when applied to member functions. A const member function can change member variables marked mutable , but you've indicated that this is not possible in your case.

How is it possible to have both const and non-const version of a function?

There are legitimate uses of having two member functions with the same name with one const and the other not, such as the begin and end iterator functions, which return non-const iterators on non-const objects, and const iterators on const objects, but if it's casting from const to do something, it smells like fish.


1 Answers

The relevant quote from the standard is 5.2.3 [expr.type.conv]/2

The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete ob- ject type or the (possibly cv-qualified) void type, creates a prvalue of the specified type,which is value- initialized (8.5; no initialization is done for the void() case). [Note: if T is a non-class type that is cv-qualified, the cv-qualifiers are ignored when determining the type of the resulting prvalue (3.10). —end note ]

The wording in the standard explicitly mentions (in non-normative form) that for non-class types the const-volatile qualification is dropped, but in your case the type is a class, and the note does not apply. It seems that VS is applying the same rule that is applied for non-class types.

like image 176
David Rodríguez - dribeas Avatar answered Nov 14 '22 22:11

David Rodríguez - dribeas