У меня есть следующий шаблонный код
#include <vector>
#include <array>
#include <iostream>
template<typename T1>
void foo(std::vector<T1> bar) {
std::cout << "GENERIC" << std::endl;
}
template<typename T1>
void foo(std::vector<std::vector<T1>> bar) {
std::cout << "SPECIFIC (vector)" << std::endl;
}
template<typename T1, int SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
std::cout << "SPECIFIC (array)" << std::endl;
}
int main() {
std::vector<std::vector<int>> a(2, std::vector<int> { 1, 2, 3});
std::vector<std::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});
foo(a);
foo(b);
}
который производит
SPECIFIC (vector)
GENERIC
Мне интересно, почему версия вектора-вектора вызывается с конкретным шаблоном, а версия вектора-массива вызывается с универсальным?
vector
на всех из них. Смотрите здесьОтветы:
Вы должны использовать
std::size_t
вместоint
. беги сюдаИзменить: На самом деле, ваши комментарии и моя интуиция о коде заставили меня копаться в теме. На первый взгляд, стандартные разработчики (как и я) ожидают, что компилятор преобразует
int
ихstd::size_t
(потому что они оба являются целочисленным типом, а неявное преобразование очень тривиально) и выбираетvoid foo(std::vector<std::array<T1, SIZE>> bar)
наилучшую специализацию. Так что, читая страницу вывода аргументов шаблона, я нашел это:Как всегда, конечно, вы должны прочитать несколько раз, чем один раз, чтобы понять, что это значит :)
Получается интересный результат.
Наша желаемая специализация уже не выбрана, но если бы компилятор был вынужден выбирать, это было бы ошибкой.
запустить код
Еще одна интересная вещь:
Если бы не типовой аргумент шаблона не был выведен, не было бы ограничения, которое заставляет типы аргумента и шаблона быть одинаковыми.
запустить код
источник
size_t
...Я думаю, что это просто из-за одной строки из
[temp.deduct.call]/4
Чтобы уточнить,
A
значит параметр, из[temp.deduct.call]/1
Как уже указывалось, переход
template<typename T1, int SIZE>
наtemplate<typename T1, size_t SIZE>
исправление проблемы, которую вы видите. Как указано в[temp.deduct.call]/4
, компилятор ищет вывод,A
который идентиченA
. Так как anstd::array
имеет аргументы шаблона<class T, size_t N>
(from[array.syn]
), на самом деле его второй параметр -size_t
нетint
.Следовательно, для вывода из шаблона ваша общая функция
template<typename T1>
способна точно соответствовать типуA
, где ваш специалистtemplate<typename T1, int SIZE>
не является точным соответствием. Я считаю, что MSVC является неправильным в своем выводе.источник