작성
·
358
0
template<typename T>
void printSet(set<T>& s)
{
for (set<T>::iterator it = s.begin(); it != s.end(); ++it)
{
cout << (*it) << " ";
}
}
// 동작 X
printSet<int>(s);
컨테이너 클래스의 iterator를 사용하려고합니다.
템플릿을 활용해서 작성을 하려는데 set<T>::iterator로는 동작하지 않는데 그 이유가 궁금합니다.
감사합니다.
답변 1
0
둘 중 하나로 바꿔주시면 됩니다!
C++ 표준에서 그 이유는 다음과 같습니다.
전용 가능한 이름 검색에서 타입 이름이 나오거나 typename으로 정의 되지 않는 한 템플릿 선언이나 정의에서 사용되고 템플릿 매개변수에 의존적인 이름은 타입의 이름으로 쓰일 수 없다고 가정한다
한마디로 set<T>에 종속적인 멤버 변수를 사용 못합니다.
따라서 typename을 붙여주지 않으면, set<T>에 소속된 iterator를 몰라서 발생하는 문제입니다.
아 조금 더 이해가 되어가고 있는 것 같습니다.
"의존적인"은 어떻게 알 수 있는건가요?
class C3
{
};
template<typename T>
class C1
{
public:
T a;
C3 z;
};
template<typename T>
class C2
{
public:
T a; // 정상, (1) typename 없이 통과
C1<T>::C3 b; // 오류, (2) typename C1<T>::C3 b; 로 선언해야 빌드 통과
};
의존적이다는 기준이 T에 따라 변수의 타입이 정해진다는 것이라면,
(1), (2) 모두 T에 의존적인 것 같은데 typename이 (1)에는 안붙어도 통과됩니다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class C3
{
};
template<typename T>
class C1
{
public:
T a;
C3 z;
};
template<typename T>
class C2
{
public:
T a; // 정상, (1) typename 없이 통과
typename C1<T>::C3 b; // 오류, (2) typename C1<T>::C3 b; 로 선언해야 빌드 통과
C1<T> c; // 통과, (3) typename 없이 통과
};
(3)케이스도 추가하였습니다.
종속적인 관점에서 3가지 경우의 차이점이 어떤건지 궁금합니다.
이런 부분들은 스스로 고민해보시기 바랍니다.
프로그래머에게 스스로 학습하고 구글링 하는 것은 필수 덕목입니다.
구글에 typename 검색을 1분만 하면 아주 자세하게
다양한 예제를 동반해서 정보가 나오기 때문에,
스스로 예상한 바를 검증해보세요
https://wikidocs.net/433
감사합니다.
주신 자료랑 또 키워드 검색해서 공부하였습니다.
아직 부족해서 온전히 이해하지는 못했고 "중첩 의존 이름"의 경우 typename을 적용하여 컴파일러에게 타입형임을 알린다라고 정리하게되었습니다, 처음 주신 답변 "한마디로 확정되지 않은, T라는 타입에 의존적인 무엇인가를 사용하려면 앞에다 typename을 붙이라는겁니다."도 일맥상통하는 내용이라고 생각이 드네요!
감사합니다.
설명을 제대로 이해하지 못한 것 같아 조금 더 질문을 드리고 싶습니다.
첨부해주신 C++표준의 내용이 조금 어렵게 느껴집니다... (한국말을 이해 못하는 느낌이네요 ㅠㅠ) 특히, "전용 가능한 이름 검색", "의존적인 이름"은 어떤 뜻인지 잘 모르겠네요...
auto의 경우는 컴파일러가 begin()에 따라 자동으로 맞춰주기 때문에 이상 없음으로 받아들일 수 있었습니다만, typename의 사용은 조금 의아스럽습니다.
T가 선언, 정의에 단독으로 사용된 경우는 자료형이 함께 전달되기 때문에 사용가능하지만
set<T>로 템플릿 매개변수를 활용하여 범위 지정 연산자 (::)를 통한 선언 및 정의에서는 set<T>가 typename인지 아닌지를 몰라서 붙인다는건가요..??