Type conversion, constness and overloading mixed

Hi geeks!)

Could someone describe what is the general rules for solving the following?

It looks like in first case the type conversion is avoided and const function is called for non-const object, but in second the precedence is for non-const argument with type conversion allowed...

What is the output of the following C++ program?
#include <iostream>

class A
{
public:
A(int i) : m_i(i) { }

public:
int operator()(int i = 0) const { return m_i + i; }

operator int () const { return m_i; }

private:
int m_i;

friend int g(const A&);
};

int f(char c)
{
return c;
}

int g(const A& a)
{
return a.m_i;
}

int main()
{
A f(2), g(3);

std::cout << f(1) << g(f) << std::endl;

return 0;
}
Answer: 35
I believe that the answer is compiler-specific and is undefined by the C++ standard because you're changing the value of f.m_i and using the value in two separate occurances in the same statement.

To describe what is happening, we should first get rid of the stuff that you don't need in the code above.

Delete this: The functions aren't ever called.
1
2
3
4
5
6
7
8
int f(char c)
{
return c;
}
int g(const A& a)
{
return a.m_i;
}


Also delete friend int g(const A&); as it isn't used.

You end up with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>

class A
{
public:
  A(int i) : m_i(i) { }
  
public:
  int operator()(int i) const { return m_i + i; }
  operator int ()       const { return m_i; }
  
private:
  int m_i;
};

int main()
{
  A f(2), g(3); // f.m_i = 2, g.m_i = 3
  
  std::cout << f(1) // calls int operator()(int i), f.m_i is now 3
            << g(f) // calls operator int() for f which returns 2, 
                    // then calls int operator()(int i), g.m_i is now 3+2 = 5. 
            << std::endl;
  
  return 0;
}


The operator int() for f returns 2 because the functions in line 21 are excecuted BEFORE the functions in line 20. Which function is excecuted first is not specified in the C++ standard.
Last edited on
Ok, let's assume that there is
f(1);
g(f);
so getting rid of calling sequence ambiguity.

What I don't understand is why are you saying "Delete this: The functions aren't ever called", what's the rule to choose the class's methods instead of global functions?

Thank you!
Your code has nothing to do with class methods VS global functions
1) Your class doesn have methods
2) You local variables in main are named exactly the same as global functions
*obviously* the local variable names are going to be used. So f, g are referring to the object of class a in std::cout << f(1) << g(f) << std::endl; and not the functions f, g
To elaborate on codewalker's explanation,

You have int g(const A& a); in the global scope. You also have A g; in the local scope which will support g(f); through a few operator functions defined in the class. When an ambiguity exists, the compiler will generally take the local scope versions and give you a warning when you compile.

At one point I had this problem in some code that I was editing:
1
2
3
4
5
6
7
8
9
10
11
12
int a;
void somefunction()
{
    int a;
    a = 5;
}
int main()
{
    a = 0;
    somefunction();
    cout << a;
}

Since the local definition in somefunction() was defined at the very top of the function which was several hundred lines from where it was set, this was VERY hard to debug and it took a while to figure out why the global a wasn't being set. This is a similar (and simplified) version of what we are explaining to you with the ambiguous function calls.
Last edited on
Got it. Thanks!
Stewbond wrote:
because you're changing the value of f.m_i and using the value in two separate occurances in the same statement.
There is no such thing. The methods are const, that means that you can't modify the state of the object.
The behaviour is well defined

Shiva dzhee wrote:
const function is called for non-const object,
That's expected, as you didn't provide an overload for non-const object
closed account (zb0S216C)
ne555 wrote:
"The methods are const, that means that you can't modify the state of the object."

Not if a data member is mutable.

Wazzak
Topic archived. No new replies allowed.