C ++ identical method signature but different return type

I saw the following code:

template <class T> class Type { public: Type() {} T& operator=(const T& rhs) {value() = rhs; return value();} T& value() {return m_value;} T value() const {return m_value;} private: T m_value; }; 

Why does the compiler not complain about

  T& value() {return m_value;} T value() const {return m_value;} 

and how do you know which one is being called?

+8
c ++ templates method-overloading
source share
3 answers

The two functions do not really match. Only the second function is declared as a const member function. If the object from which the element is called is const , the last option is used. If the object is not const , the first option is used.

Example:

 void any_func(const Type *t) { something = t->value(); //second `const` version used } void any_func2(Type *t) { something = t->value(); //first non-`const` version used } 

If both functions were declared not const or both were declared const , the compiler (one way or another) will complain.

+13
source share

Why does the compiler not complain about

Because const counts another function signature. Your assumption that the function signatures are identical is incorrect.
A function marked as const will be called for any instance of const or a Type<T> link.

and how do you know which one is being called?

Put the cout statement in the function and check the following cases:

 template <class T> class Type { public: Type() {} T& operator=(const T& rhs) {value() = rhs; return value();} T& value() { std::cout << "non const version" << std endl; return m_value; } T value() const { std::cout << "const version" << std endl; return m_value; } private: T m_value; }; 

 int main() { Type<int> t; t.value(); Type<int> rt = t; rt.value(); Type<int>* pt = &t; pt->value(); const Type<int> ct; ct.value(); const Type<int>& crt = t; crt.value(); const Type<int>* pct = &t; pct->value(); } 

The assignment operator will invoke the non-content version.


The const version looks better like

 const T& value() const { std::cout << "const version" << std endl; return m_value; } 

because you cannot always rely on RVO (return value optimization), and additional copies can be made (especially for older compiler implementations).


Also note that the assignment operator should return a reference to the current instance:

  Type& operator=(const T& rhs) {value() = rhs; return *this;} 
+7
source share

A few words about the priority of function resolution. The compiler distinguishes const / non const functions as follows:

If a class has only a const function with a given name and a list of arguments, it will be called for constant and non-constant objects. After calling this function, the object will "assume" constness (even if it was not const), which means that the function can only call other const functions.

If the class has only a non-constant function, it will be called for non-constant objects. Attempting to call this function on const objects will result in a compilation error.

If the class has both functions, the const version will be used for const objects, the non-const version will be used for non-constant objects.

Thanks to @owacoder for pointing out my attention to the initial mix in the description.

+5
source share

All Articles