Неоднозначный вызов функции класса

168
01 мая 2019, 01:10

Почему компилятор пишет

error: call to member function 'foo' is ambiguous

ведь я явно указал тип литерала unsigned long long?

class A {
    using LL = long long;
public:
    void foo(unsigned LL) {}
    void foo(LL) {}
};
int main() {
    A a;
    a.foo(42ull);
}
Answer 1

Вот здесь

void foo(unsigned LL) {}

LL должно восприниматься как параметр функции типа unsigned int. А далее, поскольку у вас есть функции от unsigned int и long long, а передаете вы unsigned long long - точного соответствия нет, и вызов неоднозначен...

class A {
    using LL = long long;
    using ULL = unsigned long long;
public:
    void foo(ULL) {}
    void foo(LL) {}
};

и все заработает :)

typedef - не препроцессор, присоединение unsigned к определенному таким образом типу не работает.

Answer 2

На самом деле первый вариант перегруженной функции-члена foo имеет параметр типа unsigned int, а не unsigned long long int, как вы, наверное, хотели задать. В данном случае LL - имя параметра, а не typedef-name.

dcl.spec#3:

If a type-name is encountered while parsing a decl-specifier-seq, it is interpreted as part of the decl-specifier-seq if and only if there is no previous defining-type-specifier other than a cv-qualifier in the decl-specifier-seq.

Таким образом, компилятор при overload resolution встречает 2 кандидата: void foo(unsigned int) и void foo(long long int), оба из которых требуют integral conversion, поэтому имеют одинаковый ранг, и компилятор выдаёт описанное вами сообщение.

READ ALSO
Одинаковы ли типы const int и int в шаблонах?

Одинаковы ли типы const int и int в шаблонах?

Почему программа выводит 00, ведь const int = int, то есть вызов идёт к одной и той же функции, а значит статическая переменная увеличится на единицу...

131
Передача лямбды шаблонной функции

Передача лямбды шаблонной функции

Как передать в шаблон с параметром-функцией лямбду? Почему так не работает?

195