Почему C++ не допускает использование двух шаблонов функций/классов с тем же именем, отличающихся только типом несимметричного шаблона (интегрального типа)?

Когда я пытаюсь это сделать, компилятор дает ошибку. Я пробовал как с VC++, так и с g++.

Это в равной степени относится к шаблонам функций и шаблонам классов (хотя для шаблонов функций ошибка компилятора возникает только в том случае, когда и когда создается шаблон функции, ошибка компилятора для шаблона класса происходит сразу же, когда компилятор сталкивается с определением второго класса).

Вот пример шаблона функции:

template <unsigned int>
void Foo() {}

template <signed int>    // Same name, only difference is the type of the
void Foo() {}            // non-type template parameter (of integral type)


Foo<10U>(); // COMPILER ERROR.

Выше, почему компилятор не может создать экземпляр Foo <unsigned int>()?

Я обнаружил, что это не проблема, если вторая версия шаблона function/class имеет параметр шаблона типа. Это также не проблема, если вторая версия функции шаблона/класса имеет или несимметричный шаблонный параметр нецелого типа:

template <unsigned int>
void Foo() {}

template <unsigned int*>  // Non-type template parameter
void Foo() {}             // of non-integral type

template <typename T>     // Type template parameter
void Foo() {}


Foo<10U>();               // OK

Так что, если бы я должен был догадаться, я бы сказал, что он имеет какое-то отношение к тому, что компилятор может преобразовывать значения интегральных типов? Но это не останавливает C++ от допуска двух функций перегрузки, которые отличаются только типом интегрального параметра.

Спасибо!

Ответ 1

Это действительно так, вы смогли написать два шаблона просто отлично. Они просто становятся непригодными при создании экземпляров. Причина в том, что для выбора шаблона нет "разрешения перегрузки". Единственное требование, наложенное на аргумент шаблона, отличного от типа, выглядит следующим образом:

[temp.arg.nontype]/2

Аргумент шаблона для не-type template-parameter должен быть преобразованным константным выражением типа шаблона-параметра.

И 10u - преобразованное константное выражение как int и unsigned int type. Действителен как аргумент для перегрузки.