[완료]c++ 템플릿 기법을 이용해서 여러 타입의 데이터를 저장하는 링크드 리스트를 만들 수 있는지 궁금해서 질문 올립니다.

gyutae1990의 이미지

c++ 템플릿 기법을 이용해서 여러 타입의 데이터를 저장하는 링크드 리스트를
만들 수 있는지 궁금해서 질문 올립니다.

아직 구현은 안보았지만 제작한다면
템플릿 링크드 리스트로 구현하되 템플릿 인자 타입은 void* 로 모든
타입을 가리킬 수 있게 하는 방식으로 하려고 합니다.

노드 정의는
template (typename DATA_TYPE)
class Node{

DATA_TYPE *_data; //현재 가르키는 자료형
Node *_next; //다음 노드 주소
string _type; //_data의 타입 저장
}

해두고 Node 생성시 _data가 void*로 저장되면 타입을 모르므로
string _type으로 타입을 기록해두려고 합니다.

그리고
_data 값을 반환시 _type도 같이 반환하려고 합니다.

혹시 이렇게 링크드 리스틀 만든 분 계신가요??!

pynoos의 이미지

STL이 그렇게 만들어져있죠.

jick의 이미지

Template의 기본 개념을 잘 이해 못하신 것 같습니다. 템플릿은 런타임에 타입을 변경해서 이것 저것 넣을 수 있는 개념이 아니라, 컴파일할 때 무슨 타입을 쓸지 완전히 정해지는 기능입니다.

void *로 형변환을 해서 이것저것을 넣는 것은 가능은 하지만 C++을 배우는 중이라면 최대한 사용하지 않는 것을 추천하고 싶습니다. (그리고 그렇게 하려면 굳이 템플릿을 쓸 이유가 하나도 없습니다. 그냥 void형 포인터만 하나 있으면 되지요.)

void *를 안 쓴다고 하면 "그러면 여러 가지 타입을 넣는 리스트는 어떻게 만드나요?"라는 질문이 나올 수 있는데, "그게 왜 필요하죠? 그런 리스트가 필요 없게 프로그램 구조를 다시 설계해 보세요"가 C++의 기본적인 철학(?)에 맞는 방향입니다.

* 물론 C++은 지저분한 언어고 온 세상의 오만가지 사용 케이스에 다 때려박을 수 있도록 만들어졌기 때문에 원한다면 할 수 있습니다. 그다지 추천을 안한다 뿐이죠. -_-

gyutae1990의 이미지

template (typename DATA_TYPE)
class Node{
DATA_TYPE *_data; //현재 가르키는 자료형
Node *_next; //다음 노드 주소
string _type; //_data의 타입 저장
}
에서 굳이 template을 하지 않고 바로 void *_data를 해주어도 됬군요.
근데 굳이 void*가 아닌 template을 써야하는 이유에 대해 찾아봤습니다.

제가 알아본 바에 의해 void*보다 template이 더 좋은 이유는

[1]
void*의 단점은 형의 안정성을 포기하는 것에 있습니다.
이유는 어떤 형이 들어가도 되기 때문입니다.

반면 템플릿 자료형은 형이 정해져 있으므로 컴파일 타임에 형식 검사를
통해 오류를 파악하기가 쉽습니다.
(안정성 측면에서 쉽군요.)

[2] 가독성 측면에서 void*로 딸랑 있는 것보다 DATA_TYPE, ELEMENT_TYPE 등으로
간단하게 추상하게 되어 이해하기 쉽습니다.
(가독성 측면에서 쉽군요.)

[3] 템플릿은 더 쉽게 작성할 수 있습니다. 수동으로 특수화를 만드는 대신 클래스 또는 함수의 제네릭 버전을 하나만 만듭니다.
(이는 코드 생산성 측면에서 유리하군요.)

의문도 몇 개 더 생겨버렸습니다.
의문의 첫 번째 단추인 템플릿에 대해 더 알아봐야 겠습니다.

[참고]
https://kldp.org/node/26159

 의 이미지

완료된 질문이라고 하셨지만, 혹시 나중에 다른 분이 참조하실까 싶어서,
그리고 저도 나름대로 궁금한 부분이 있어서 올립니다.

Quote:
c++ 템플릿 기법을 이용해서 여러 타입의 데이터를 저장하는 링크드 리스트를
만들 수 있는지 궁금해서 질문 올립니다.

질문에서 말하는 "여러 타입의 데이터를 저장하는 링크드 리스트"가 무엇인지 확실하지 않은데
대충 두 가지 해석이 있어 보입니다.

(1) 똑같은 코드로 integer list, float list 등을 생성할 수 있지만 리스트 안의 노드끼리는 모두 같은 타입인 경우.

그러니까 [1, 2, 3, 4]도 만들고 [1.0, 2.0, 3.0, 4.0]도 만들 수 있지만 [1, 2.0, 3, 4.0] 같은 건 못 만드는 거죠.

그런 건 template을 쓰는 편이 정석적이고, 사실 딱히 새로 만들 필요도 없습니다. std::list 참조.

(2) list 안에 타입 불문하고 뭐든 들어갈 수 있는 경우.

예컨대 파이썬처럼 [1, 2.0, "three"] 이런 식으로 아무렇게나 넣을 수 있는 거라면... 음. 좀 더 어려운 문제입니다.

질문글에 있는 코드에서 list node별로 타입을 저장하는 것으로 볼 때 (2)의 경우가 아닐까 싶은데요.

일단 몇 가지 짚고 넘어가죠.

Quote:
[1]
void*의 단점은 형의 안정성을 포기하는 것에 있습니다.
이유는 어떤 형이 들어가도 되기 때문입니다.
반면 템플릿 자료형은 형이 정해져 있으므로 컴파일 타임에 형식 검사를
통해 오류를 파악하기가 쉽습니다.
(안정성 측면에서 쉽군요.)

컴파일 타임에 형식 검사를 하기 위해서는, 당연히 컴파일 타임에 형식이 알려져 있어야 됩니다.
(2)처럼 리스트에 어떤 타입이 어떻게 들어갈지 런타임이 되기 전엔 알 수가 없는 경우 컴파일 타임 검사를 기대한다는 건 말이 안 되는 거죠.

Quote:
[2] 가독성 측면에서 void*로 딸랑 있는 것보다 DATA_TYPE, ELEMENT_TYPE 등으로
간단하게 추상하게 되어 이해하기 쉽습니다.
(가독성 측면에서 쉽군요.)

사실 꼭 가독성만 바란다면 typedef void *DATA_TYPE 하는 방법도 있긴 합니다. 네, 구차해 보이는 거 알고 있습니다. :(

아무튼,

(2)를 꼭 구현하고 싶다면, 제 짧은 소견으로는 템플릿에 더하여 "클래스 상속을 이용한 다형성" 기능을 이용하면, 최소한 "리스트에 임의 타입을 넣는 것"까지는 가능할 것으로 보입니다. 간단히 예를 들어 설명드리면, 혹시 java 아시는지요? java에서는 모든 객체가 Object의 자식 클래스이지요. 그러니 그런 Object 같은 걸 만들어서 std::list<Object*> 같은 걸 만들면 어떻겠어요?

...문제는 일단 들어간 값을 빼서 사용하려고 할 때입니다. 부모 클래스의 포인터/레퍼런스로 가리켜지는 자식 클래스 객체를 받게 됐는데 그게 정확히 어떤 자식 클래스인지 모르면 꽤 답답한 상황이 되거든요.

어떻게든 할 방법이 없는 건 아닌데(어떻게든 타입을 따로 저장해두거나, 가상 함수 호출로 구분하거나, RTTI를 쓰거나, 등등.) 정말로 모든 타입을 담을 수 있는 범용성을 가지도록 구현하는 게 그렇게 깔끔할 거라는 생각이 안 듭니다. 런타임 오버헤드가 생길 가능성도 크고요.

이쯤되면 그런 임의 타입 컨테이너의 개념이 애초에 C++에 그다지 맞지 않는 것이 아닌가 싶기도 합니다. 아니면 그저 제 실력이 미치지 않는 것일 수도 있고요..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.