Разрешение перегруженного вызова функции с помощью DWORD - PullRequest
0 голосов
/ 03 ноября 2018

При использовании Microsoft C ++ 2017, 64-битная сборка, следующая строка кода генерирует ошибку компиляции с неоднозначным вызовом перегруженной функции:

print(pmc.PageFaultCount);

У меня определены следующие функции печати в надежде однозначно охватить все целочисленные типы общего пользования:

void print(int32_t n);
void print(int64_t n);
void print(uint32_t n);
void print(uint64_t n);

pmc.PageFaultCount объявлено как DWORD, что задокументировано как 32-разрядное целое число без знака. Я ожидал, что для выбора перегрузки uint32_t.

Как это неоднозначно?

Более того, если вышеупомянутого набора перегрузок недостаточно для вывода какого-либо целого числа, какой набор перегрузок будет достаточным?

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Проблема в том, что int, long, long long и их неподписанные версии всегда имеют разные типы, даже если они имеют одинаковое количество битов. Например. is_same_v<int, long> всегда false.

Зная это, DWORD определяется как unsigned long в 64-битной Windows, а uint32_t и uint64_t определяются как unsigned int и unsigned long long соответственно. Таким образом, среди ваших перегрузок нет идеального соответствия для DWORD. Но, поскольку unsigned long a.k.a DWORD можно неявно преобразовать во все эти типы, вы получите неоднозначный вызов.

Примечание: на платформе, где long и unsigned long являются 64-битными типами, вы получите ту же неоднозначность, только с long long и unsigned long long соответственно.

Чтобы решить вашу проблему, вам нужно добавить недостающие перегрузки long и unsigned long, чтобы действительно охватить все интегральные типы, чтобы обеспечить идеальное соответствие для всех из них.

Возможно, вы захотите переписать сигнатуры вашей функции с псевдонимов (u)intXX_t до int, long, long long и их неподписанных вариантов, чтобы сделать более очевидным, что все покрыто. Вы также можете захотеть перегрузку для short и unsigned short.

0 голосов
/ 03 ноября 2018

DWORD - псевдоним для unsigned long, а uint32_t - псевдоним для unsigned int. Таким образом, вам нужен еще один набор перегрузок, принимающий long и unsigned long (и, вероятно, для unsigned long long long long, unsigned short, short, unsigned char, signed char, обычный char, wchar_t, char16_t, char32_t, std::byte и типы перечислителей).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...