Saya memiliki kode templated berikut
#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);
}
yang menghasilkan
SPECIFIC (vector)
GENERIC
Saya bertanya-tanya mengapa versi vektor-of-vektor dipanggil dengan templat khusus, tetapi versi vektor-of-array disebut dengan generik?
vector
pada semuanya. Lihat di siniJawaban:
Anda harus menggunakan
std::size_t
bukanint
. lari kesiniSunting: Sebenarnya, komentar dan intuisi saya tentang kode membuat saya menggali topik. Pada pandangan pertama, pengembang standar (seperti saya) mengharapkan kompiler untuk dikonversi
int
kestd::size_t
(karena mereka adalah tipe integral dan secara implisit mengkonversi sangat sepele) dan memilihvoid foo(std::vector<std::array<T1, SIZE>> bar)
spesialisasi terbaik. Jadi ketika membaca halaman pengurangan argumen template saya menemukan ini:Seperti biasa, tentu saja, Anda harus membaca beberapa kali lebih banyak dari sekali untuk memahami artinya :)
Jadi hasil yang menarik keluar.
Sudah spesialisasi yang kami inginkan tidak dipilih tetapi jika kompiler terpaksa memilih, itu akan menjadi kesalahan.
jalankan kode
Hal menarik lainnya adalah:
Jika argumen templat non-tipe tidak dideduksi, tidak akan ada batasan yang memaksa argumen dan tipe templat sama.
jalankan kode
sumber
size_t
...Saya pikir ini hanya karena satu baris dari
[temp.deduct.call]/4
Untuk memperjelas,
A
berarti parameter, dari[temp.deduct.call]/1
Seperti yang telah ditunjukkan, mengubah
template<typename T1, int SIZE>
untuktemplate<typename T1, size_t SIZE>
memperbaiki masalah yang Anda lihat. Seperti yang dinyatakan dalam[temp.deduct.call]/4
, kompiler sedang mencari untuk menyimpulkanA
yang identik denganA
. Karenastd::array
argumen templat memiliki<class T, size_t N>
(dari[array.syn]
), parameter kedua sebenarnyasize_t
, bukanint
.Oleh karena itu, untuk pengurangan templat, fungsi generik Anda
template<typename T1>
mampu mencocokkan dengan tepat jenisA
, di mana-karena spesialis Andatemplate<typename T1, int SIZE>
bukan pencocokan tepat . Saya percaya MSVC salah dalam deduksi.sumber