6
#include <iostream>
using namespace std;

struct Y;

struct X
{
    X(const Y&) { cout << "converting constructor" << endl; }
};

struct Y
{
    operator X() { cout << "conversion function" << endl; }
};

void f(X x) {}

int main()
{
    Y y;
    f(y);
}

In the above the conversion function is given priority to the converting constructor by my compiler (gcc 4.6.1), however in the standard it states that:

User-defined conversions are applied only where they are unambiguous

It would seem that there is ambiguity in this case. Can anyone explain the contradiction?

I would have expected the above to not compile. I'm also pretty sure years ago that Scott Meyers wrote about this specific example and said that it wouldn't compile. What am I missing?

iammilind
  • 68,093
  • 33
  • 169
  • 336
Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319

2 Answers2

6

Because X constructor wants a const argument, it prefers the operator. If you remove the const in the X constructor then compiler complains about ambiguity. If there are more than one functions with reference parameters, the one with the most relaxed const qualification is preferred.

A good answer here

Community
  • 1
  • 1
perreal
  • 94,503
  • 21
  • 155
  • 181
1

There is no ambiguity here, the only valid conversion is provided by the conversion function.
Note that yis not a const, your conversion constructor needs a const argument.

There would be a ambiguity, If your conversion constructor took a non const reference.

Online Sample:

#include <iostream>
using namespace std;

struct Y;

struct X
{
    X(Y&) { cout << "converting constructor" << endl; }

};

struct Y
{
    operator X() { cout << "conversion function" << endl; }
};

void f(X x) {}

int main()
{
    Y y;
    f(y);
    return 0;  
}

Output:

prog.cpp: In member function ‘Y::operator X()’:
prog.cpp:13: warning: no return statement in function returning non-void
prog.cpp: In function ‘int main()’:
prog.cpp:21: error: conversion from ‘Y’ to ‘X’ is ambiguous
prog.cpp:13: note: candidates are: Y::operator X()
prog.cpp:8: note: X::X(Y&)

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Btw, there is nothing c++11 specific in the code sample.The code is valid even in c++03. – Alok Save Mar 12 '12 at 02:57
  • What is the reason for Downvoting this? Please specify reasons when you downvote to indicate what you feel is wrong and if you cannot think of any logical/technical reasons for justifying the downvote, please consider yourself not qualified for downvoting. – Alok Save Mar 12 '12 at 09:31
  • i am sorry. i thought that the reason i downvoted it is already given in the accepted answer. the constructor *can* be used by the conversion. but it is not preferred. – Johannes Schaub - litb Mar 12 '12 at 19:43
  • @JohannesSchaub-litb: Yes it *Can* be used but there is **no ambiguity** here, the order in which the const or non const versions will be selected is well defined.Not sure If my choice of words seems to indicate anything otherwise in the answer. – Alok Save Mar 13 '12 at 02:45