0

I have a question regarding function matching. consider this code:

main.hpp:

struct Foo
{
  Foo(double = 1.0)
  {
    std::cout << "Foo constructor\n";
  }
  operator double()
  {
    std::cout << "Foo double\n";
    return double(1.0);
  }
  operator int()
  {
    std::cout << "Foo int\n";
    return int(1);
  }
};

void Bar(Foo &f)
{
  std::cout << "Bar Foo\n";
}

void Bar(int)
{
  std::cout << "Bar int\n";
}

main.cpp:

double d;

Bar(Foo(d));

output:

Foo constructor
Foo int
Bar int

however if i change void Bar(Foo &f) to void Bar(const Foo &f), output changes to

Foo constructor
Bar Foo

I'm not sure why const causes to call Bar(Foo) instead of Bar(int) even though Foo(d) is not const.

glucomine
  • 35
  • 4
  • 4
    Because a rvalue (temporary) `Foo(d)` cannot bind to a `Foo&` while it can to `const Foo&`. – Passer By Jul 08 '17 at 09:08
  • Possible duplicate of [How come a non-const reference cannot bind to a temporary object?](https://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object) – Passer By Jul 08 '17 at 09:10

1 Answers1

3

Foo(d) is a rvalue/temporary, it can't bind to a Foo& but it can bind to a const Foo& which is why it can call void Bar(const Foo &f), const Foo& is a better match here than conversion to int and then Bar(int) because that requires an extra user-defined conversion. When using Foo& the compiler isn't allowed to call Bar(Foo&) but it sees that it can make a conversion to int and then call Bar(int), so it does.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122