Odd Conditional Operator Bug

This is my first post so bear with me.

What I'm trying to figure out is why "cout << (result.IntCheck() ? result.Float() : result ) << endl;" calls a constructor for a new Fraction object after result.IntCheck() returns true and result.Float() returns a double value.

The reason I know that a constructor is called after result.Float() returns is because I used gnu debugger.

Driver:
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 <cstdlib>
#include <iostream>
#include <fstream>
#include "Fraction.h"
using std::cout;
using std::endl;

#define DATA "fraction270.txt"

int main()
{
    Fraction first, second, result;
    char op;
    std::ifstream dataFile( DATA, std::ios::in );
    if ( !dataFile )
    {
       std::cerr << DATA << "could not be opened." << endl;
       exit( 1 );
    }

    dataFile >> first >> op >> second;
    result = first * second;
    cout << (result.IntCheck() ? result.Float() : result ) << endl;
    system("PAUSE");
    return 0;
}


Class Definition:
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "Fraction.h"
#include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>
using std::ostream;
using std::istream;

void Fraction::Assign(int n, int d)
{
    num = n;
    if (d != 0) 
            den = d;
    else den = 1;
} 

Fraction::Fraction(int n, int d)
{
    Assign(n, d);
}

ostream& operator<<( ostream& output, const Fraction& fraction )
{
    output << fraction.num << "/" << fraction.den;
    return output;
}

istream& operator>>( istream& input, Fraction& fraction )
{
    std::string buffer;
    input >> buffer;
    fraction.Assign( std::atoi(buffer.substr(0, buffer.find("/")).c_str()), 
                     std::atoi(buffer.substr(buffer.find("/") + 1).c_str()));
    return input;
}

const Fraction Fraction::operator*(Fraction right)
{
    Fraction product((num *  right.num), (den * right.den));
    product.Simplify();
    return product;
}

double Fraction::Float()
{
    return (double)num/den;
}

void Fraction::Simplify()
{
    if(num != 0)
    {
        if(den % num == 0)
        {
            den /= num;
            num = 1;
        }
        else
        {
            int factor;
            if(num < den)
                factor = std::sqrt(num);
            if(den < num)
                factor = std::sqrt(den);
            while(factor > 1)
            {
                if((den % factor == 0)&&(num % factor == 0))
                {
                   num /= factor;
                   den /= factor;
                }
                else
                    --factor;
            }
        }
    }
}

bool Fraction::IntCheck()
{
    if(num % den == 0)
            return true;
    else
        return false;
}


Class Header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iosfwd>

class Fraction
{
    friend std::ostream& operator<<( std::ostream& output, const Fraction& fraction );
    friend std::istream& operator>>( std::istream& input, Fraction& fraction );
public:
    Fraction(int n = 0, int d = 1);
    void Assign(int n, int d);
    const Fraction operator*(Fraction right);
    double Float();
    void Simplify();
    bool IntCheck();
private:
    int num;
    int den;
};


Expected Output:
6


Actual Output:
6/1
The conditional operator

result.IntCheck() ? result.Float() : result

shall return the common type for operands result.Float() and result.

Expression result.Float() has type double while expression result has type Fraction. An object of type Fraction can not be converted to type double because your class has no such conversion function. However an object of type double can be converted to an object of type Fraction because the class contains constructor that takes one argument

Fraction(int n = 0, int d = 1);

So the common type for the expression will be Fraction. The compiler creates a temporary object of type Fraction using the following call

Fraction( result.Float() );
Thanks. Neither my professor nor my textbook mention a common return type. Nor wikipedia... Nor http://www.cplusplus.com/doc/tutorial/operators/ ...

I consider this an oversight.
If you can translate from Russian to English for example by means of google translate then you can read my topic about a bug in std::common_type in MS VC++ 2010. I think it would be useful.

http://cpp.forum24.ru/?1-3-0-00000051-000-0-0-1343642437
cppreference has an explanation of the conditional operator's return type:

http://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator
Topic archived. No new replies allowed.