다음과 같은 템플릿 코드가 있습니다
#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
벡터 버전이 특정 템플릿으로 호출되는 이유가 궁금하지만 배열 벡터 버전이 일반으로 호출되는 이유는 무엇입니까?
답변
template<typename T1, size_t SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
std::cout << "SPECIFIC (array)" << std::endl;
}
std::size_t
대신 사용해야 합니다 int
.
여기로 달려
편집 :
실제로, 귀하의 의견과 코드에 대한 나의 직감으로 인해 주제를 파헤 쳤습니다. 언뜻보기에, 표준 개발자 (나 같은)는 컴파일러 int
가 std::size_t
(완전한 유형이고 암시 적으로 변환하는 것이 매우 간단하기 때문에 ) 컴파일러가 변환 void foo(std::vector<std::array<T1, SIZE>> bar)
하고 최고의 전문화로 선택하기 를 기대합니다. 따라서 템플릿 인수 공제 페이지 를 읽는 동안 나는 이것을 발견했습니다.
비 유형 템플릿 매개 변수가 매개 변수 목록에 사용되고 해당 템플릿 인수가 추론되는 경우 추론 된 템플릿 인수의 유형 (포함 템플릿 매개 변수 목록에 지정된 참조는 유지됨)이 cv-qualifiers가 삭제되고 템플리트 인수가 배열 바운드에서 추론되는 경우를 제외하고는 형식이 아닌 템플리트 매개 변수가 정확합니다.이 경우 항상 일체형이 허용되지만 부울 한 유형도 허용됩니다.
항상 그렇듯이, 당신은 그것이 무엇을 의미하는지 이해하기 위해 몇 번 이상 읽어야합니다 🙂
흥미로운 결과가 나옵니다.
우리가 원하는 전문화는 이미 선택되어 있지 않지만 컴파일러가 강제로 선택했다면 오류가 발생합니다.
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::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});
foo(b); // P = std::vector<std::array<int,(int)SIZE>
// A = std::vector<std::array<int,(unsigned_long)SIZE>>
// error: deduced non-type template argument does not have the same
// type as its corresponding template argument */
}
또 다른 흥미로운 것은 :
비 타입 템플릿 인자가 추론되지 않았다면, 인자와 템플릿 타입을 동일하게 강제하는 제한은 없습니다.
#include <vector>
#include <array>
#include <iostream>
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::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});
foo<int,3>(b);
}
답변
나는 이것이 단순히 한 줄 때문 이라고 생각 합니다.[temp.deduct.call]/4
일반적으로, 추론 프로세스는 추론 된 A를 A와 동일하게 만드는 템플리트 인수 값을 찾으려고 시도합니다.
명확히하기 위해 A
매개 변수를 의미합니다.[temp.deduct.call]/1
… 호출의 해당 인수 유형으로 인수 공제를 고려하십시오 (A라고 부릅니다) …
이미 지적했듯이, 변경 하면 현재보고있는 문제 template<typename T1, int SIZE>
가 template<typename T1, size_t SIZE>
해결됩니다. 에서 언급했듯이 [temp.deduct.call]/4
컴파일러는와 A
동일한 것을 추론하려고 합니다 A
. 이 때문에 std::array
템플릿 인수가 <class T, size_t N>
(에서 [array.syn]
), 그것은 두 번째 매개 변수는 사실에의 size_t
하지 int
.
따라서 템플릿 공제의 경우 일반 함수는 의 유형 template<typename T1>
과 정확하게 일치 할 수 있습니다 A
. 여기서 특수한 함수 template<typename T1, int SIZE>
는 정확히 일치 하지 않습니다 . MSVC의 추론이 틀렸다고 생각합니다.