해결된 질문
작성
·
282
3
강의 듣고 궁금해서 아래 와 같이 나열 하였는데 sum 에러가 발생합니다. 혹시 추가 설명 가능한가요?
template<typename Any>
Any sum(Any, Any);
template<typename Any>
Any sum(int, Any);
template<typename Any>
Any sum(Any, float);
template<typename Any>
Any sum(int, float);
int main() {
int a = 1, b = 2;
float c = 3.14, d = 1.592;
cout << sum(a, b) << "\n" << endl;
//sum 에러
cout << sum(a, c) << "\n" << endl;
//sum 에러
cout << sum(c, d) << "\n" << endl;
//sum 에러
cout << sum(b, d) << "\n" << endl;
//sum 에러
}
template<typename Any>
Any sum(Any a, Any b) {
return a + b;
}
template<typename Any>
Any sum(int a, Any b) {
return a + b;
}
template<typename Any>
Any sum(Any a, float b) {
return a + b;
}
template<typename Any>
Any sum(int a, float b) {
return a + b;
}
답변 2
3
Template은 변수의 데이터형 결정을 유보한다는 점에서 매력적이지만 주의해서 사용하여야 합니다.
자, 저희 잠깐만 복습의 시간을 가져볼까요?
바로 이전 강의인 '함수 오버로딩'에서 함수 오버로딩은 매혹적인 기능이지만,
사용할 수 없는 두 가지 경우에 대해서 살펴본 바 있습니다.
혹시 어떠한 이유로 에러가 발생했는지 감이 잡히실까요?
하나씩 경우를 살펴보겠습니다.
ex1)의 경우
sum함수를 호출할 때 int형 매개변수 a와 b를 사용하고 있습니다.
자, 그렇다면 sum 함수 A, B, C, D 중 어떤 경우가 ex1가 대응될 수 있나요?
첫 번째로 A가 대응될 수 있습니다.
ex1의 경우에서 A의 템플릿 Any는 int형으로 대응될 것 입니다.
다음으로 B에도 대응될 수 있습니다.
B의 경우 int형 매개변수와 Any형 매개변수를 취하는데,
ex1의 경우에서 템플릿 Any가 int에 대응되서 사용될 수 있겠지요?
따라서 ex1의 경우 대응되는 함수가 두개이기 때문에 에러가 발생합니다.
ex2)의 경우
ex2는 sum 함수를 호출할 때 int형 매개변수와 float형 매개변수를 사용하고 있습니다.
이번에는 B와 C에 대응될 수 있기에 에러가 발생합니다.
ex3)의 경우
ex3는 float과 float을 사용하고 있습니다.
이번에는 A와 C에 대응될 수 있기에 에러가 발생합니다.
ex4)의 경우
ex4는 ex2와 마찬가지로 int와 float을 사용하고 있습니다.
마찬가지로 B와 C에 대응될 수 있기에 에러가 발생합니다.
.
자, 저희 여기에서 만족하지 말고 에러를 해결해볼까요?
에러가 발생한 원인은 함수를 호출 할 때 대응되는 함수의 원형이 두개 이상이었기 때문입니다.
따라서 대응되는 경우를 하나로 일치시켜주면 해결할 수 있을 것 같습니다.
ex1은 int와 int를,
ex2와 ex4는 int와 float을,
ex3는 float과 float을 요구하고 있습니다.
함수의 오버로딩만을 사용한다면 아래와 같이 코딩할 수 있겠네요!
#include <iostream>
using namespace std;
int sum(int a, int b) {
return a + b;
}
float sum(int a, float b) {
return a + b;
}
float sum(float a, float b) {
return a + b;
}
int main() {
int a = 1, b = 2;
float c = 3.14, d = 1.592;
//ex1)
cout << sum(a, b) << "\n" << endl;
//ex2)
cout << sum(a, c) << "\n" << endl;
//ex3)
cout << sum(c, d) << "\n" << endl;
//ex4)
cout << sum(b, d) << "\n" << endl;
return 0;
}
함수의 템플릿까지 이용한다면 아래와 같이도 코딩할 수 있겠네요 :)
#include <iostream>
using namespace std;
//case A
template<typename Any>
Any sum(int a, Any b) {
return a + b;
}
//case B
template<typename Any>
float sum(float a, Any b) {
return a + b;
}
int main() {
int a = 1, b = 2;
float c = 3.14, d = 1.592;
//ex1)
cout << sum(a, b) << "\n" << endl;
//ex2)
cout << sum(a, c) << "\n" << endl;
//ex3)
cout << sum(c, d) << "\n" << endl;
//ex4)
cout << sum(b, d) << "\n" << endl;
return 0;
}
이 경우에서 case A와 case B의 return형에 주목해봅시다.
case A의 경우에는 Any의 타입이 float이냐 int냐에 따라,
return형 역시 float 혹은 int로 바뀌어야 합니다.
따라서 함수의 데이터형을 선언할 때 Any로 선언한 것을 확인할 수 있습니다.
반면에 case B의 경우 이미 float형 인자를 받고 있기 때문에,
return 역시 항상 float형으로 해주면 되겠죠?
물론 c++에서는 int형과 float형의 경우 자동으로 데이터형 변환이 발생하기 때문에,
이렇게 리턴형을 맞춰주는 과정이 없더라도 표면적으로 보이는 에러는 발생하지 않겠지만
float형에서 int형으로 형변환이 발생할 때,
소수점부의 소실이 있을 수 있을 겁니다.
혹시 이해가 되셨을까요?
1
답변에 사용될 코드입니다.
질문자 님께서 올려주신 코드와 동일하니 주석을 확인해주시면 될 것 같습니다 :)
#include <iostream>
using namespace std;
//A
template<typename Any>
Any sum(Any a, Any b) {
return a + b;
}
//B
template<typename Any>
Any sum(int a, Any b) {
return a + b;
}
//C
template<typename Any>
Any sum(Any a, float b) {
return a + b;
}
//D
template<typename Any>
Any sum(int a, float b) {
return a + b;
}
int main() {
int a = 1, b = 2;
float c = 3.14, d = 1.592;
//ex1)
cout << sum(a, b) << "\n" << endl;
//ex2)
cout << sum(a, c) << "\n" << endl;
//ex3)
cout << sum(c, d) << "\n" << endl;
//ex4)
cout << sum(b, d) << "\n" << endl;
return 0;
}
이해가 잘되었습니다. 자세한 설명을 해주셔서 감사합니다. 형변환 발생으로 소수점이 소실 되는 부분역시 직접 테스트 해보았습니다.
함수 오버로딩에서 사용할수 없는 두가지 경우가 정말 중요하네요.