Если у нас есть функция шаблона, которая принимает непиковый параметр типа int
или short
, компилятор жалуется на неоднозначность следующего вызова:
// Definition
template <int I> void foo() { std::cout << "I: " << I << '\n'; }
template <short S> void foo() { std::cout << "S: " << S << '\n'; }
// Usage
foo<0>(); // Ambiguous, int or short?
Сначала я не был удивлен этим поведением, буквальный 0
мог быть int
или short
, но если мы попробуем это:
// Definition
void foo(int i) { std::cout << "i: " << i << '\n'; }
void foo(short s) { std::cout << "s: " << s << '\n'; }
// Usage
foo(0); // "i: 0"!
Вызов foo
однозначен! он принимает перегрузку int
(даже если версия шаблона не была). Ну, немного подумав, это не удивительное поведение, ведь нет способа указать литерал short
, поэтому компилятор считает, что 0
- это int
(это поведение по умолчанию AFAIK), в чтобы однозначно вызвать версию short
не templated foo
, мы можем явно создать экземпляр short
:
foo(0); // "i: 0"
foo(short{0}); // "s: 0"
Итак, я думал, что это однозначно определит шаблонную версию, но это не так:
foo<int{0}>(); // Ambiguous call, candidates are int and short versions
foo<short{0}>(); // Ambiguous call, candidates are int and short versions
call of overloaded 'foo()' is ambiguous foo<int{0}>(); note: candidates are: void foo() [with int I = 0] void foo() [with short int S = 0] call of overloaded 'foo()' is ambiguous foo<short{0}>(); note: candidates are: void foo() [with int I = 0] void foo() [with short int S = 0]
Последнее, что я пробовал, это использовать экземпляры вместо литералов:
template <int I> void foo() { std::cout << "I: " << I << '\n'; }
template <short S> void foo() { std::cout << "S: " << S << '\n'; }
void foo(int i) { std::cout << "i: " << i << '\n'; }
void foo(short s) { std::cout << "s: " << s << '\n'; }
constexpr int i{1};
constexpr short s{5};
int main()
{
foo(i); // "i: 1"
foo(s); // "s: 5"
foo<i>(); // Ambiguous! (expected "I: 1")
foo<s>(); // Ambiguous! (expected "S: 5")
return 0;
}
Без успеха, как вы можете... Итак, какой вопрос?
- Почему вызов templated
foo
неоднозначен? (обратите внимание, что шаблоныfoo
не имеют версииint
, поэтому недвусмысленны). - Почему вызов templated
foo
остается неоднозначным даже после указания типа вызова? (обратите внимание, что шаблонныйfoo
не работает нормально).
Спасибо.