1

When compiling a sample code on g++ (v4.7.3), got error:

$ g++ -std=c++11 te2b.cc
te2b.cc: In function ‘int main(int, char**)’:
te2b.cc:17:19: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
te2b.cc:10:6: note: candidate 1: void notify(std::string, int)
te2b.cc:7:6: note: candidate 2: void notify(const char*, ...)

The following is sample code. Don't see why the ambiguity: the compiler should know to map call to notify() in main() to the first declaration. void notify(const char *fmt, ...).

#include <vector>
#include <iostream>
#include <unordered_map>
#include <stdarg.h>
using namespace std;
char notifyBuf[0x100000] = "\x06\x00\x00\x00" "notify""s";
void notify(const char *fmt, ...) {
    //....
}
void notify(string s, int maxSize = 0) {
    if (maxSize && (maxSize < s.size())) {
        s.erase(maxSize);
    }
    notify("%s\n", s.c_str());
}
int main(int argc, char *argv[]) {
    notify("%5d ", 89);    
    return 0;
}

Any ideas? Thanks.

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
packetie
  • 4,839
  • 8
  • 37
  • 72
  • That's a warning, not an error. Did you Google its text? This has been answered many times. – Lightness Races in Orbit Sep 07 '15 at 16:23
  • @Niall array to pointer is a standard conversion sequence, the other you mention is user-defined, so... no, not this one is ambiguous. `89` is an exact match for `int`, while `const char*` is better for a raw string literal than `std::string` – Piotr Skotnicki Sep 07 '15 at 16:32
  • @Niall: Even when use use explicitly `const char*`, it is ambiguous [Demo](http://coliru.stacked-crooked.com/a/d2139662dc197a73) – Jarod42 Sep 07 '15 at 16:32
  • Thanks guys for the discussion. Agree it's a warning, but in my testing, it always refers to the second declaration `void notify(string s, int maxSize = 0)`. Wonder if there is a way to call the first declaration in `main()`. Thanks. – packetie Sep 07 '15 at 16:45
  • @codingFun Yes, switch the order of the arguments on the second function to be (int, string) – Fabio Sep 07 '15 at 16:47
  • Any reason to use ellipsis `...` instead of variadic template ? – Jarod42 Sep 07 '15 at 16:48
  • @dietbacon, don't think it's legal to do `void notify(int maxSize = 0, string s )`. Thx anyway. – packetie Sep 07 '15 at 16:49
  • @Jarod42, no particular reason to use ellipsis. All I need to do is to be able to invoke any of the two declarations in application (`main()`). How would you rewrite the declaration based on variadic template? – packetie Sep 07 '15 at 16:56
  • 1
    @codingFun: Something like [that](http://coliru.stacked-crooked.com/a/ff98f057680584d2) – Jarod42 Sep 07 '15 at 17:07
  • @Jarod42, thanks for the link. It solves my problem. Could you write it up as an answer? – packetie Sep 07 '15 at 17:12
  • It fixes your problem, but doesn't answer your question, so I don't convert my comment in answer. – Jarod42 Sep 07 '15 at 17:23
  • @Jarod42, thanks a lot ! – packetie Sep 07 '15 at 17:25

1 Answers1

3

§ 13.3.3 [over.match.best]/p2:

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

(1.3) — for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that, [...]

Given function call notify("%5d ", 89); and two overloads:

void notify(const char*, ...);   // F1
void notify(std::string, int);   // F2

the compiler has the following set of implicit conversion sequences for the arguments of F1:

  • ICS0(F1) - a standard conversion sequence (an array to pointer conversion)
  • ICS1(F1) - an ellipsis conversion sequence

and the following set of implicit conversion sequences for the arguments of F2:

  • ICS0(F2) - a user defined conversion sequence (via a constructor)
  • ICS1(F2) - a standard conversion sequence (an identity conversion)

Because ICS0(F1) is better than ICS0(F2), but, in turn, ICS1(F2) is better than ICS1(F1), the compiler can't choose between the two.*


* § 13.3.3.2 [over.ics.rank]/p2:

When comparing the basic forms of implicit conversion sequences (as defined in 13.3.3.1):

— a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and

— a user-defined conversion sequence (13.3.3.1.2) is a better conversion sequence than an ellipsis conversion sequence (13.3.3.1.3).

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
  • Wish there is a way to tell compiler to use dictionary order for a particular function name (`notify` in this case) :-) – packetie Sep 07 '15 at 17:28