Mam następujący kod szablonu
#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);
}
który produkuje
SPECIFIC (vector)
GENERIC
Zastanawiam się, dlaczego wersja wektor-wektor jest wywoływana z określonym szablonem, ale wersja wektor-tablica jest wywoływana z ogólną?
vector
z nich wszystkich. Zobacz tutajOdpowiedzi:
Powinieneś użyć
std::size_t
zamiastint
. biegnij tutajEdycja: W rzeczywistości twoje komentarze i moja intuicja dotycząca kodu skłoniły mnie do zagłębienia się w temat. Na pierwszy rzut oka standardowy programista (jak ja) oczekuje, że kompilator przekonwertuje się
int
nastd::size_t
(ponieważ oba są typem integralnym, a konwersja domyślna jest bardzo trywialna) i wybierzevoid foo(std::vector<std::array<T1, SIZE>> bar)
najlepszą specjalizację. Tak więc podczas czytania strony z dedukcją argumentów szablonu znalazłem to:Jak zawsze, oczywiście, musisz przeczytać kilka razy więcej niż raz, aby zrozumieć, co to znaczy :)
Tak więc pojawia się interesujący wynik.
Nasza pożądana specjalizacja nie jest już wybrana, ale gdyby kompilator został zmuszony do wyboru, byłby to błąd.
uruchom kod
Kolejną interesującą rzeczą jest:
Gdyby nie wywnioskowano argumentu innego niż typ szablonu, nie byłoby żadnych ograniczeń, które wymuszałyby takie same argumenty i typy szablonów.
uruchom kod
źródło
size_t
...Myślę, że wynika to po prostu z jednej linii z
[temp.deduct.call]/4
Wyjaśnienie
A
oznacza parametr od[temp.deduct.call]/1
Jak już wspomniano, zmiana w
template<typename T1, int SIZE>
celutemplate<typename T1, size_t SIZE>
rozwiązania problemu, który widzisz. Jak stwierdzono w[temp.deduct.call]/4
, kompilator chce wydedukowaćA
identyczny zA
. Ponieważ anstd::array
ma argumenty szablonu<class T, size_t N>
(od[array.syn]
), jego drugim parametrem jest tak naprawdęsize_t
nieint
.Dlatego do odliczenia szablonu twoja ogólna funkcja
template<typename T1>
jest w stanie dopasować dokładnie typA
, gdzie-jak twoja specjalizacjatemplate<typename T1, int SIZE>
nie jest dokładnym dopasowaniem. Uważam, że MSVC nie ma racji w swoich wnioskach.źródło